This source file includes following definitions.
- print_udp
- udp_err
- udp_check
- udp_send_check
- udp_send
- udp_sendto
- udp_write
- udp_ioctl
- udp_recvfrom
- udp_read
- udp_connect
- udp_close
- udp_rcv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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>
52 #include <linux/in.h>
53 #include <linux/errno.h>
54 #include <linux/timer.h>
55 #include <linux/termios.h>
56 #include <linux/mm.h>
57 #include "inet.h"
58 #include "dev.h"
59 #include "ip.h"
60 #include "protocol.h"
61 #include "tcp.h"
62 #include "skbuff.h"
63 #include "sock.h"
64 #include "udp.h"
65 #include "icmp.h"
66
67
68 #define min(a,b) ((a)<(b)?(a):(b))
69
70
71 static void
72 print_udp(struct udphdr *uh)
73 {
74 if (inet_debug != DBG_UDP) return;
75
76 if (uh == NULL) {
77 printk("(NULL)\n");
78 return;
79 }
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));
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95 void
96 udp_err(int err, unsigned char *header, unsigned long daddr,
97 unsigned long saddr, struct inet_protocol *protocol)
98 {
99 struct udphdr *th;
100 struct sock *sk;
101 struct iphdr *ip=(struct iphdr *)header;
102
103 header += 4*ip->ihl;
104
105 th = (struct udphdr *)header;
106
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));
109
110 sk = get_sock(&udp_prot, th->source, daddr, th->dest, saddr);
111
112 if (sk == NULL)
113 return;
114
115 if (err < 0)
116 {
117 sk->err = -err;
118 sk->error_report(sk);
119 return;
120 }
121
122 if (err & 0xff00 ==(ICMP_SOURCE_QUENCH << 8)) {
123 if (sk->cong_window > 1)
124 sk->cong_window = sk->cong_window/2;
125 return;
126 }
127
128 sk->err = icmp_err_convert[err & 0xff].errno;
129
130
131 if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED) {
132 sk->err=ECONNREFUSED;
133 }
134 sk->error_report(sk);
135 }
136
137
138 static unsigned short
139 udp_check(struct udphdr *uh, int len,
140 unsigned long saddr, unsigned long daddr)
141 {
142 unsigned long sum;
143
144 DPRINTF((DBG_UDP, "UDP: check(uh=%X, len = %d, saddr = %X, daddr = %X)\n",
145 uh, len, saddr, daddr));
146
147 print_udp(uh);
148
149 __asm__("\t addl %%ecx,%%ebx\n"
150 "\t adcl %%edx,%%ebx\n"
151 "\t adcl $0, %%ebx\n"
152 : "=b"(sum)
153 : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256)
154 : "cx","bx","dx" );
155
156 if (len > 3) {
157 __asm__("\tclc\n"
158 "1:\n"
159 "\t lodsl\n"
160 "\t adcl %%eax, %%ebx\n"
161 "\t loop 1b\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" );
166 }
167
168
169 __asm__("\t movl %%ebx, %%ecx\n"
170 "\t shrl $16,%%ecx\n"
171 "\t addw %%cx, %%bx\n"
172 "\t adcw $0, %%bx\n"
173 : "=b"(sum)
174 : "0"(sum)
175 : "bx", "cx");
176
177
178 if ((len & 2) != 0) {
179 __asm__("\t lodsw\n"
180 "\t addw %%ax,%%bx\n"
181 "\t adcw $0, %%bx\n"
182 : "=b"(sum), "=S"(uh)
183 : "0"(sum) ,"1"(uh)
184 : "si", "ax", "bx");
185 }
186
187
188 if ((len & 1) != 0) {
189 __asm__("\t lodsb\n"
190 "\t movb $0,%%ah\n"
191 "\t addw %%ax,%%bx\n"
192 "\t adcw $0, %%bx\n"
193 : "=b"(sum)
194 : "0"(sum) ,"S"(uh)
195 : "si", "ax", "bx");
196 }
197
198
199 return((~sum) & 0xffff);
200 }
201
202
203 static void
204 udp_send_check(struct udphdr *uh, unsigned long saddr,
205 unsigned long daddr, int len, struct sock *sk)
206 {
207 uh->check = 0;
208 if (sk && sk->no_check)
209 return;
210 uh->check = udp_check(uh, len, saddr, daddr);
211 if (uh->check == 0) uh->check = 0xffff;
212 }
213
214
215 static int
216 udp_send(struct sock *sk, struct sockaddr_in *sin,
217 unsigned char *from, int len)
218 {
219 struct sk_buff *skb;
220 struct device *dev;
221 struct udphdr *uh;
222 unsigned char *buff;
223 unsigned long saddr;
224 int size, tmp;
225 int err;
226
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),
229 from, len));
230
231 err=verify_area(VERIFY_READ, from, len);
232 if(err)
233 return(err);
234
235
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);
239
240 skb->mem_addr = skb;
241 skb->mem_len = size;
242 skb->sk = NULL;
243 skb->free = 1;
244 skb->arp = 0;
245
246
247 buff = skb->data;
248 saddr = 0;
249 dev = NULL;
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;
255
256 if (tmp < 0 ) {
257 sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
258 return(tmp);
259 }
260 buff += tmp;
261 saddr = dev->pa_addr;
262 DPRINTF((DBG_UDP, "UDP: >> MAC+IP len=%d\n", tmp));
263
264 skb->len = tmp + sizeof(struct udphdr) + len;
265 skb->dev = dev;
266 #ifdef OLD
267
268
269
270
271
272 if (len > dev->mtu) {
273 #else
274 if (skb->len > 4095)
275 {
276 #endif
277 printk("UDP: send: length %d > mtu %d (ignored)\n", len, dev->mtu);
278 sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
279 return(-EMSGSIZE);
280 }
281
282
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);
288
289
290 memcpy_fromfs(buff, from, len);
291
292
293 udp_send_check(uh, saddr, sin->sin_addr.s_addr, skb->len - tmp, sk);
294
295
296 sk->prot->queue_xmit(sk, dev, skb, 1);
297
298 return(len);
299 }
300
301
302 static int
303 udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
304 unsigned flags, struct sockaddr_in *usin, int addr_len)
305 {
306 struct sockaddr_in sin;
307 int tmp;
308 int err;
309
310 DPRINTF((DBG_UDP, "UDP: sendto(len=%d, flags=%X)\n", len, flags));
311
312
313 if (flags)
314 return(-EINVAL);
315 if (len < 0)
316 return(-EINVAL);
317 if (len == 0)
318 return(0);
319
320
321 if (usin) {
322 if (addr_len < sizeof(sin)) return(-EINVAL);
323 err=verify_area(VERIFY_READ, usin, sizeof(sin));
324 if(err)
325 return err;
326 memcpy_fromfs(&sin, usin, sizeof(sin));
327 if (sin.sin_family && sin.sin_family != AF_INET)
328 return(-EINVAL);
329 if (sin.sin_port == 0)
330 return(-EINVAL);
331 } else {
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;
336 }
337
338 if(!sk->broadcast && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
339 return -EACCES;
340 sk->inuse = 1;
341
342
343 tmp = udp_send(sk, &sin, from, len);
344
345
346 release_sock(sk);
347 return(tmp);
348 }
349
350
351 static int
352 udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
353 unsigned flags)
354 {
355 return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
356 }
357
358
359 int
360 udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
361 {
362 int err;
363 switch(cmd) {
364 case DDIOCSDBG:
365 {
366 int val;
367
368 if (!suser()) return(-EPERM);
369 err=verify_area(VERIFY_READ, (void *)arg, sizeof(int));
370 if(err)
371 return err;
372 val = get_fs_long((int *)arg);
373 switch(val) {
374 case 0:
375 inet_debug = 0;
376 break;
377 case 1:
378 inet_debug = DBG_UDP;
379 break;
380 default:
381 return(-EINVAL);
382 }
383 }
384 break;
385 case TIOCOUTQ:
386 {
387 unsigned long amount;
388
389 if (sk->state == TCP_LISTEN) return(-EINVAL);
390 amount = sk->prot->wspace(sk);
391 err=verify_area(VERIFY_WRITE,(void *)arg,
392 sizeof(unsigned long));
393 if(err)
394 return(err);
395 put_fs_long(amount,(unsigned long *)arg);
396 return(0);
397 }
398
399 case TIOCINQ:
400 {
401 struct sk_buff *skb;
402 unsigned long amount;
403
404 if (sk->state == TCP_LISTEN) return(-EINVAL);
405 amount = 0;
406 skb = sk->rqueue;
407 if (skb != NULL) {
408
409
410
411
412
413 amount = skb->len;
414 }
415 err=verify_area(VERIFY_WRITE,(void *)arg,
416 sizeof(unsigned long));
417 if(err)
418 return(err);
419 put_fs_long(amount,(unsigned long *)arg);
420 return(0);
421 }
422
423 default:
424 return(-EINVAL);
425 }
426 return(0);
427 }
428
429
430
431
432
433
434 int
435 udp_recvfrom(struct sock *sk, unsigned char *to, int len,
436 int noblock, unsigned flags, struct sockaddr_in *sin,
437 int *addr_len)
438 {
439 int copied = 0;
440 struct sk_buff *skb;
441 int er;
442
443
444
445
446
447
448 if (sk->err) {
449 int err;
450
451 err = -sk->err;
452 sk->err = 0;
453 return(err);
454 }
455
456 if (len == 0)
457 return(0);
458 if (len < 0)
459 return(-EINVAL);
460
461 if (addr_len) {
462 er=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
463 if(er)
464 return(er);
465 put_fs_long(sizeof(*sin), addr_len);
466 }
467 if(sin)
468 {
469 er=verify_area(VERIFY_WRITE, sin, sizeof(*sin));
470 if(er)
471 return(er);
472 }
473 er=verify_area(VERIFY_WRITE,to,len);
474 if(er)
475 return er;
476 skb=skb_recv_datagram(sk,flags,noblock,&er);
477 if(skb==NULL)
478 return er;
479 copied = min(len, skb->len);
480
481
482 skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
483
484
485 if (sin) {
486 struct sockaddr_in addr;
487
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));
492 }
493
494 skb_free_datagram(skb);
495 release_sock(sk);
496 return(copied);
497 }
498
499
500 int
501 udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
502 unsigned flags)
503 {
504 return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
505 }
506
507
508 int
509 udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
510 {
511 struct sockaddr_in sin;
512 int er;
513
514 if (addr_len < sizeof(sin))
515 return(-EINVAL);
516
517 er=verify_area(VERIFY_READ, usin, sizeof(sin));
518 if(er)
519 return er;
520
521 memcpy_fromfs(&sin, usin, sizeof(sin));
522 if (sin.sin_family && sin.sin_family != AF_INET)
523 return(-EAFNOSUPPORT);
524
525 if(!sk->broadcast && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
526 return -EACCES;
527
528 sk->daddr = sin.sin_addr.s_addr;
529 sk->dummy_th.dest = sin.sin_port;
530 sk->state = TCP_ESTABLISHED;
531 return(0);
532 }
533
534
535 static void
536 udp_close(struct sock *sk, int timeout)
537 {
538 sk->inuse = 1;
539 sk->state = TCP_CLOSE;
540 if (sk->dead) destroy_sock(sk);
541 else release_sock(sk);
542 }
543
544
545
546 int
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)
550 {
551 struct sock *sk;
552 struct udphdr *uh;
553
554 uh = (struct udphdr *) skb->h.uh;
555 sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
556 if (sk == NULL)
557 {
558 if (chk_addr(daddr) == IS_MYADDR)
559 {
560 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
561 }
562
563
564
565
566
567 skb->sk = NULL;
568 kfree_skb(skb, FREE_WRITE);
569 return(0);
570 }
571
572 if (uh->check && udp_check(uh, len, saddr, daddr)) {
573 DPRINTF((DBG_UDP, "UDP: bad checksum\n"));
574 skb->sk = NULL;
575 kfree_skb(skb, FREE_WRITE);
576 return(0);
577 }
578
579 skb->sk = sk;
580 skb->dev = dev;
581 skb->len = len;
582
583
584 skb->daddr = saddr;
585 skb->saddr = daddr;
586
587
588
589 if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
590 {
591 skb->sk = NULL;
592 kfree_skb(skb, FREE_WRITE);
593 release_sock(sk);
594 return(0);
595 }
596 sk->rmem_alloc += skb->mem_len;
597
598
599 DPRINTF((DBG_UDP, "<< \n"));
600 print_udp(uh);
601
602
603
604 skb_queue_tail(&sk->rqueue,skb);
605
606 skb->len = len - sizeof(*uh);
607
608 if (!sk->dead)
609 sk->data_ready(sk,skb->len);
610
611 release_sock(sk);
612 return(0);
613 }
614
615
616 struct proto udp_prot = {
617 sock_wmalloc,
618 sock_rmalloc,
619 sock_wfree,
620 sock_rfree,
621 sock_rspace,
622 sock_wspace,
623 udp_close,
624 udp_read,
625 udp_write,
626 udp_sendto,
627 udp_recvfrom,
628 ip_build_header,
629 udp_connect,
630 NULL,
631 ip_queue_xmit,
632 ip_retransmit,
633 NULL,
634 NULL,
635 udp_rcv,
636 datagram_select,
637 udp_ioctl,
638 NULL,
639 NULL,
640 ip_setsockopt,
641 ip_getsockopt,
642 128,
643 0,
644 {NULL,},
645 "UDP"
646 };