2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
6 * The User Datagram Protocol (UDP).
8 * Version: @(#)udp.c 1.0.13 06/02/93
10 * Authors: Ross Biro, <bir7@leland.Stanford.Edu>
11 * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
14 * Alan Cox : verify_area() calls
15 * Alan Cox : stopped close while in use off icmp
16 * messages. Not a fix but a botch that
17 * for udp at least is 'valid'.
18 * Alan Cox : Fixed icmp handling properly
19 * Alan Cox : Correct error for oversized datagrams
20 * Alan Cox : Tidied select() semantics.
21 * Alan Cox : udp_err() fixed properly, also now
22 * select and read wake correctly on errors
23 * Alan Cox : udp_send verify_area moved to avoid mem leak
24 * Alan Cox : UDP can count its memory
25 * Alan Cox : send to an uknown connection causes
26 * an ECONNREFUSED off the icmp, but
28 * Alan Cox : Switched to new sk_buff handlers. No more backlog!
29 * Alan Cox : Using generic datagram code. Even smaller and the PEEK
30 * bug no longer crashes it.
31 * Fred Van Kempen : Net2e support for sk->broadcast.
32 * Alan Cox : Uses skb_free_datagram
33 * Alan Cox : Added get/set sockopt support.
34 * Alan Cox : Broadcasting without option set returns EACCES.
35 * Alan Cox : No wakeup calls. Instead we now use the callbacks.
36 * Alan Cox : Use ip_tos and ip_ttl
39 * This program is free software; you can redistribute it and/or
40 * modify it under the terms of the GNU General Public License
41 * as published by the Free Software Foundation; either version
42 * 2 of the License, or (at your option) any later version.
45 #include <asm/system.h>
46 #include <asm/segment.h>
47 #include <linux/types.h>
48 #include <linux/sched.h>
49 #include <linux/fcntl.h>
50 #include <linux/socket.h>
51 #include <linux/sockios.h>
53 #include <linux/errno.h>
54 #include <linux/timer.h>
55 #include <linux/termios.h>
68 #define min(a,b) ((a)<(b)?(a):(b))
72 print_udp(struct udphdr
*uh
)
74 if (inet_debug
!= DBG_UDP
) return;
80 printk("UDP: source = %d, dest = %d\n", ntohs(uh
->source
), ntohs(uh
->dest
));
81 printk(" len = %d, check = %d\n", ntohs(uh
->len
), ntohs(uh
->check
));
86 * This routine is called by the ICMP module when it gets some
87 * sort of error condition. If err < 0 then the socket should
88 * be closed and the error returned to the user. If err > 0
89 * it's just the icmp type << 8 | icmp code.
90 * Header points to the ip header of the error packet. We move
91 * on past this. Then (as it used to claim before adjustment)
92 * header points to the first 8 bytes of the udp header. We need
93 * to find the appropriate port.
96 udp_err(int err
, unsigned char *header
, unsigned long daddr
,
97 unsigned long saddr
, struct inet_protocol
*protocol
)
101 struct iphdr
*ip
=(struct iphdr
*)header
;
105 th
= (struct udphdr
*)header
;
107 DPRINTF((DBG_UDP
,"UDP: err(err=%d, header=%X, daddr=%X, saddr=%X, protocl=%X)\n\
108 sport=%d,dport=%d", err
, header
, daddr
, saddr
, protocol
, (int)th
->source
,(int)th
->dest
));
110 sk
= get_sock(&udp_prot
, th
->source
, daddr
, th
->dest
, saddr
);
113 return; /* No socket for error */
115 if (err
< 0) /* As per the calling spec */
118 sk
->error_report(sk
); /* User process wakes to see error */
122 if (err
& 0xff00 ==(ICMP_SOURCE_QUENCH
<< 8)) { /* Slow down! */
123 if (sk
->cong_window
> 1)
124 sk
->cong_window
= sk
->cong_window
/2;
128 sk
->err
= icmp_err_convert
[err
& 0xff].errno
;
130 /* It's only fatal if we have connected to them. */
131 if (icmp_err_convert
[err
& 0xff].fatal
&& sk
->state
== TCP_ESTABLISHED
) {
132 sk
->err
=ECONNREFUSED
;
134 sk
->error_report(sk
);
138 static unsigned short
139 udp_check(struct udphdr
*uh
, int len
,
140 unsigned long saddr
, unsigned long daddr
)
144 DPRINTF((DBG_UDP
, "UDP: check(uh=%X, len = %d, saddr = %X, daddr = %X)\n",
145 uh
, len
, saddr
, daddr
));
149 __asm__("\t addl %%ecx,%%ebx\n"
150 "\t adcl %%edx,%%ebx\n"
151 "\t adcl $0, %%ebx\n"
153 : "0"(daddr
), "c"(saddr
), "d"((ntohs(len
) << 16) + IPPROTO_UDP
*256)
160 "\t adcl %%eax, %%ebx\n"
162 "\t adcl $0, %%ebx\n"
163 : "=b"(sum
) , "=S"(uh
)
164 : "0"(sum
), "c"(len
/4) ,"1"(uh
)
165 : "ax", "cx", "bx", "si" );
168 /* Convert from 32 bits to 16 bits. */
169 __asm__("\t movl %%ebx, %%ecx\n"
170 "\t shrl $16,%%ecx\n"
171 "\t addw %%cx, %%bx\n"
177 /* Check for an extra word. */
178 if ((len
& 2) != 0) {
180 "\t addw %%ax,%%bx\n"
182 : "=b"(sum
), "=S"(uh
)
187 /* Now check for the extra byte. */
188 if ((len
& 1) != 0) {
191 "\t addw %%ax,%%bx\n"
198 /* We only want the bottom 16 bits, but we never cleared the top 16. */
199 return((~sum
) & 0xffff);
204 udp_send_check(struct udphdr
*uh
, unsigned long saddr
,
205 unsigned long daddr
, int len
, struct sock
*sk
)
208 if (sk
&& sk
->no_check
)
210 uh
->check
= udp_check(uh
, len
, saddr
, daddr
);
211 if (uh
->check
== 0) uh
->check
= 0xffff;
216 udp_send(struct sock
*sk
, struct sockaddr_in
*sin
,
217 unsigned char *from
, int len
)
227 DPRINTF((DBG_UDP
, "UDP: send(dst=%s:%d buff=%X len=%d)\n",
228 in_ntoa(sin
->sin_addr
.s_addr
), ntohs(sin
->sin_port
),
231 err
=verify_area(VERIFY_READ
, from
, len
);
235 /* Allocate a copy of the packet. */
236 size
= sizeof(struct sk_buff
) + sk
->prot
->max_header
+ len
;
237 skb
= sk
->prot
->wmalloc(sk
, size
, 0, GFP_KERNEL
);
238 if (skb
== NULL
) return(-ENOMEM
);
242 skb
->sk
= NULL
; /* to avoid changing sk->saddr */
246 /* Now build the IP and MAC header. */
250 DPRINTF((DBG_UDP
, "UDP: >> IP_Header: %X -> %X dev=%X prot=%X len=%d\n",
251 saddr
, sin
->sin_addr
.s_addr
, dev
, IPPROTO_UDP
, skb
->mem_len
));
252 tmp
= sk
->prot
->build_header(skb
, saddr
, sin
->sin_addr
.s_addr
,
253 &dev
, IPPROTO_UDP
, sk
->opt
, skb
->mem_len
,sk
->ip_tos
,sk
->ip_ttl
);
254 skb
->sk
=sk
; /* So memory is freed correctly */
257 sk
->prot
->wfree(sk
, skb
->mem_addr
, skb
->mem_len
);
261 saddr
= dev
->pa_addr
;
262 DPRINTF((DBG_UDP
, "UDP: >> MAC+IP len=%d\n", tmp
));
264 skb
->len
= tmp
+ sizeof(struct udphdr
) + len
; /* len + UDP + IP + MAC */
268 * This code used to hack in some form of fragmentation.
269 * I removed that, since it didn't work anyway, and it made the
270 * code a bad thing to read and understand. -FvK
272 if (len
> dev
->mtu
) {
277 printk("UDP: send: length %d > mtu %d (ignored)\n", len
, dev
->mtu
);
278 sk
->prot
->wfree(sk
, skb
->mem_addr
, skb
->mem_len
);
282 /* Fill in the UDP header. */
283 uh
= (struct udphdr
*) buff
;
284 uh
->len
= htons(len
+ sizeof(struct udphdr
));
285 uh
->source
= sk
->dummy_th
.source
;
286 uh
->dest
= sin
->sin_port
;
287 buff
= (unsigned char *) (uh
+ 1);
289 /* Copy the user data. */
290 memcpy_fromfs(buff
, from
, len
);
292 /* Set up the UDP checksum. */
293 udp_send_check(uh
, saddr
, sin
->sin_addr
.s_addr
, skb
->len
- tmp
, sk
);
295 /* Send the datagram to the interface. */
296 sk
->prot
->queue_xmit(sk
, dev
, skb
, 1);
303 udp_sendto(struct sock
*sk
, unsigned char *from
, int len
, int noblock
,
304 unsigned flags
, struct sockaddr_in
*usin
, int addr_len
)
306 struct sockaddr_in sin
;
310 DPRINTF((DBG_UDP
, "UDP: sendto(len=%d, flags=%X)\n", len
, flags
));
312 /* Check the flags. */
320 /* Get and verify the address. */
322 if (addr_len
< sizeof(sin
)) return(-EINVAL
);
323 err
=verify_area(VERIFY_READ
, usin
, sizeof(sin
));
326 memcpy_fromfs(&sin
, usin
, sizeof(sin
));
327 if (sin
.sin_family
&& sin
.sin_family
!= AF_INET
)
329 if (sin
.sin_port
== 0)
332 if (sk
->state
!= TCP_ESTABLISHED
) return(-EINVAL
);
333 sin
.sin_family
= AF_INET
;
334 sin
.sin_port
= sk
->dummy_th
.dest
;
335 sin
.sin_addr
.s_addr
= sk
->daddr
;
338 if(!sk
->broadcast
&& chk_addr(sin
.sin_addr
.s_addr
)==IS_BROADCAST
)
339 return -EACCES
; /* Must turn broadcast on first */
342 /* Send the packet. */
343 tmp
= udp_send(sk
, &sin
, from
, len
);
345 /* The datagram has been sent off. Release the socket. */
352 udp_write(struct sock
*sk
, unsigned char *buff
, int len
, int noblock
,
355 return(udp_sendto(sk
, buff
, len
, noblock
, flags
, NULL
, 0));
360 udp_ioctl(struct sock
*sk
, int cmd
, unsigned long arg
)
368 if (!suser()) return(-EPERM
);
369 err
=verify_area(VERIFY_READ
, (void *)arg
, sizeof(int));
372 val
= get_fs_long((int *)arg
);
378 inet_debug
= DBG_UDP
;
387 unsigned long amount
;
389 if (sk
->state
== TCP_LISTEN
) return(-EINVAL
);
390 amount
= sk
->prot
->wspace(sk
)/*/2*/;
391 err
=verify_area(VERIFY_WRITE
,(void *)arg
,
392 sizeof(unsigned long));
395 put_fs_long(amount
,(unsigned long *)arg
);
402 unsigned long amount
;
404 if (sk
->state
== TCP_LISTEN
) return(-EINVAL
);
409 * We will only return the amount
410 * of this packet since that is all
415 err
=verify_area(VERIFY_WRITE
,(void *)arg
,
416 sizeof(unsigned long));
419 put_fs_long(amount
,(unsigned long *)arg
);
431 * This should be easy, if there is something there we\
432 * return it, otherwise we block.
435 udp_recvfrom(struct sock
*sk
, unsigned char *to
, int len
,
436 int noblock
, unsigned flags
, struct sockaddr_in
*sin
,
445 * This will pick up errors that occured while the program
446 * was doing something else.
462 er
=verify_area(VERIFY_WRITE
, addr_len
, sizeof(*addr_len
));
465 put_fs_long(sizeof(*sin
), addr_len
);
469 er
=verify_area(VERIFY_WRITE
, sin
, sizeof(*sin
));
473 er
=verify_area(VERIFY_WRITE
,to
,len
);
476 skb
=skb_recv_datagram(sk
,flags
,noblock
,&er
);
479 copied
= min(len
, skb
->len
);
481 /* FIXME : should use udp header size info value */
482 skb_copy_datagram(skb
,sizeof(struct udphdr
),to
,copied
);
484 /* Copy the address. */
486 struct sockaddr_in addr
;
488 addr
.sin_family
= AF_INET
;
489 addr
.sin_port
= skb
->h
.uh
->source
;
490 addr
.sin_addr
.s_addr
= skb
->daddr
;
491 memcpy_tofs(sin
, &addr
, sizeof(*sin
));
494 skb_free_datagram(skb
);
501 udp_read(struct sock
*sk
, unsigned char *buff
, int len
, int noblock
,
504 return(udp_recvfrom(sk
, buff
, len
, noblock
, flags
, NULL
, NULL
));
509 udp_connect(struct sock
*sk
, struct sockaddr_in
*usin
, int addr_len
)
511 struct sockaddr_in sin
;
514 if (addr_len
< sizeof(sin
))
517 er
=verify_area(VERIFY_READ
, usin
, sizeof(sin
));
521 memcpy_fromfs(&sin
, usin
, sizeof(sin
));
522 if (sin
.sin_family
&& sin
.sin_family
!= AF_INET
)
523 return(-EAFNOSUPPORT
);
525 if(!sk
->broadcast
&& chk_addr(sin
.sin_addr
.s_addr
)==IS_BROADCAST
)
526 return -EACCES
; /* Must turn broadcast on first */
528 sk
->daddr
= sin
.sin_addr
.s_addr
;
529 sk
->dummy_th
.dest
= sin
.sin_port
;
530 sk
->state
= TCP_ESTABLISHED
;
536 udp_close(struct sock
*sk
, int timeout
)
539 sk
->state
= TCP_CLOSE
;
540 if (sk
->dead
) destroy_sock(sk
);
541 else release_sock(sk
);
545 /* All we need to do is get the socket, and then do a checksum. */
547 udp_rcv(struct sk_buff
*skb
, struct device
*dev
, struct options
*opt
,
548 unsigned long daddr
, unsigned short len
,
549 unsigned long saddr
, int redo
, struct inet_protocol
*protocol
)
554 uh
= (struct udphdr
*) skb
->h
.uh
;
555 sk
= get_sock(&udp_prot
, uh
->dest
, saddr
, uh
->source
, daddr
);
558 if (chk_addr(daddr
) == IS_MYADDR
)
560 icmp_send(skb
, ICMP_DEST_UNREACH
, ICMP_PORT_UNREACH
, dev
);
563 * Hmm. We got an UDP broadcast to a port to which we
564 * don't wanna listen. The only thing we can do now is
565 * to ignore the packet... -FvK
568 kfree_skb(skb
, FREE_WRITE
);
572 if (uh
->check
&& udp_check(uh
, len
, saddr
, daddr
)) {
573 DPRINTF((DBG_UDP
, "UDP: bad checksum\n"));
575 kfree_skb(skb
, FREE_WRITE
);
583 /* These are supposed to be switched. */
588 /* Charge it to the socket. */
589 if (sk
->rmem_alloc
+ skb
->mem_len
>= sk
->rcvbuf
)
592 kfree_skb(skb
, FREE_WRITE
);
596 sk
->rmem_alloc
+= skb
->mem_len
;
598 /* At this point we should print the thing out. */
599 DPRINTF((DBG_UDP
, "<< \n"));
602 /* Now add it to the data chain and wake things up. */
604 skb_queue_tail(&sk
->rqueue
,skb
);
606 skb
->len
= len
- sizeof(*uh
);
609 sk
->data_ready(sk
,skb
->len
);
616 struct proto udp_prot
= {