This source file includes following definitions.
- 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
46
47
48
49 #include <asm/system.h>
50 #include <asm/segment.h>
51 #include <linux/types.h>
52 #include <linux/sched.h>
53 #include <linux/fcntl.h>
54 #include <linux/socket.h>
55 #include <linux/sockios.h>
56 #include <linux/in.h>
57 #include <linux/errno.h>
58 #include <linux/timer.h>
59 #include <linux/termios.h>
60 #include <linux/mm.h>
61 #include <linux/inet.h>
62 #include <linux/netdevice.h>
63 #include "snmp.h"
64 #include "ip.h"
65 #include "protocol.h"
66 #include "tcp.h"
67 #include <linux/skbuff.h>
68 #include "sock.h"
69 #include "udp.h"
70 #include "icmp.h"
71
72
73
74
75
76 struct udp_mib udp_statistics;
77
78
79
80
81 #define min(a,b) ((a)<(b)?(a):(b))
82
83
84
85
86
87
88
89
90
91
92
93
94
95 void udp_err(int err, unsigned char *header, unsigned long daddr,
96 unsigned long saddr, struct inet_protocol *protocol)
97 {
98 struct udphdr *th;
99 struct sock *sk;
100 struct iphdr *ip=(struct iphdr *)header;
101
102 header += 4*ip->ihl;
103
104
105
106
107 th = (struct udphdr *)header;
108
109 sk = get_sock(&udp_prot, th->source, daddr, th->dest, saddr);
110
111 if (sk == NULL)
112 return;
113
114 if (err & 0xff00 ==(ICMP_SOURCE_QUENCH << 8))
115 {
116 if (sk->cong_window > 1)
117 sk->cong_window = sk->cong_window/2;
118 return;
119 }
120
121
122
123
124
125
126
127
128
129 #ifdef CONFIG_I_AM_A_BROKEN_BSD_WEENIE
130
131
132
133
134
135 if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED)
136 {
137 sk->err = icmp_err_convert[err & 0xff].errno;
138 sk->error_report(sk);
139 }
140 #else
141 if (icmp_err_convert[err & 0xff].fatal)
142 {
143 sk->err = icmp_err_convert[err & 0xff].errno;
144 sk->error_report(sk);
145 }
146 #endif
147 }
148
149
150 static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr)
151 {
152 unsigned long sum;
153
154 __asm__( "\t addl %%ecx,%%ebx\n"
155 "\t adcl %%edx,%%ebx\n"
156 "\t adcl $0, %%ebx\n"
157 : "=b"(sum)
158 : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256)
159 : "cx","bx","dx" );
160
161 if (len > 3)
162 {
163 __asm__("\tclc\n"
164 "1:\n"
165 "\t lodsl\n"
166 "\t adcl %%eax, %%ebx\n"
167 "\t loop 1b\n"
168 "\t adcl $0, %%ebx\n"
169 : "=b"(sum) , "=S"(uh)
170 : "0"(sum), "c"(len/4) ,"1"(uh)
171 : "ax", "cx", "bx", "si" );
172 }
173
174
175
176
177
178 __asm__("\t movl %%ebx, %%ecx\n"
179 "\t shrl $16,%%ecx\n"
180 "\t addw %%cx, %%bx\n"
181 "\t adcw $0, %%bx\n"
182 : "=b"(sum)
183 : "0"(sum)
184 : "bx", "cx");
185
186
187
188
189
190 if ((len & 2) != 0)
191 {
192 __asm__("\t lodsw\n"
193 "\t addw %%ax,%%bx\n"
194 "\t adcw $0, %%bx\n"
195 : "=b"(sum), "=S"(uh)
196 : "0"(sum) ,"1"(uh)
197 : "si", "ax", "bx");
198 }
199
200
201
202
203
204 if ((len & 1) != 0)
205 {
206 __asm__("\t lodsb\n"
207 "\t movb $0,%%ah\n"
208 "\t addw %%ax,%%bx\n"
209 "\t adcw $0, %%bx\n"
210 : "=b"(sum)
211 : "0"(sum) ,"S"(uh)
212 : "si", "ax", "bx");
213 }
214
215
216
217
218
219 return((~sum) & 0xffff);
220 }
221
222
223
224
225
226
227
228 static void udp_send_check(struct udphdr *uh, unsigned long saddr,
229 unsigned long daddr, int len, struct sock *sk)
230 {
231 uh->check = 0;
232 if (sk && sk->no_check)
233 return;
234 uh->check = udp_check(uh, len, saddr, daddr);
235
236
237
238
239
240
241 if (uh->check == 0)
242 uh->check = 0xffff;
243 }
244
245
246 static int udp_send(struct sock *sk, struct sockaddr_in *sin,
247 unsigned char *from, int len, int rt)
248 {
249 struct sk_buff *skb;
250 struct device *dev;
251 struct udphdr *uh;
252 unsigned char *buff;
253 unsigned long saddr;
254 int size, tmp;
255
256
257
258
259
260 size = sk->prot->max_header + len;
261 skb = sk->prot->wmalloc(sk, size, 0, GFP_KERNEL);
262
263
264 if (skb == NULL)
265 return(-ENOBUFS);
266
267 skb->sk = NULL;
268 skb->free = 1;
269 skb->localroute = sk->localroute|(rt&MSG_DONTROUTE);
270
271
272
273
274
275 buff = skb->data;
276 saddr = 0;
277 dev = NULL;
278 tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr,
279 &dev, IPPROTO_UDP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl);
280 skb->sk=sk;
281
282
283
284
285
286 if (tmp < 0 )
287 {
288 sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
289 return(tmp);
290 }
291
292 buff += tmp;
293 saddr = skb->saddr;
294 skb->len = tmp + sizeof(struct udphdr) + len;
295 skb->dev = dev;
296
297
298
299
300
301 uh = (struct udphdr *) buff;
302 uh->len = htons(len + sizeof(struct udphdr));
303 uh->source = sk->dummy_th.source;
304 uh->dest = sin->sin_port;
305 buff = (unsigned char *) (uh + 1);
306
307
308
309
310
311 memcpy_fromfs(buff, from, len);
312
313
314
315
316
317 udp_send_check(uh, saddr, sin->sin_addr.s_addr, skb->len - tmp, sk);
318
319
320
321
322
323 udp_statistics.UdpOutDatagrams++;
324
325 sk->prot->queue_xmit(sk, dev, skb, 1);
326 return(len);
327 }
328
329
330 static int udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
331 unsigned flags, struct sockaddr_in *usin, int addr_len)
332 {
333 struct sockaddr_in sin;
334 int tmp;
335 int err;
336
337
338
339
340 if (flags&~MSG_DONTROUTE)
341 return(-EINVAL);
342
343
344
345
346 if (usin)
347 {
348 if (addr_len < sizeof(sin))
349 return(-EINVAL);
350 err=verify_area(VERIFY_READ, usin, sizeof(sin));
351 if(err)
352 return err;
353 memcpy_fromfs(&sin, usin, sizeof(sin));
354 if (sin.sin_family && sin.sin_family != AF_INET)
355 return(-EINVAL);
356 if (sin.sin_port == 0)
357 return(-EINVAL);
358 }
359 else
360 {
361 if (sk->state != TCP_ESTABLISHED)
362 return(-EINVAL);
363 sin.sin_family = AF_INET;
364 sin.sin_port = sk->dummy_th.dest;
365 sin.sin_addr.s_addr = sk->daddr;
366 }
367
368
369
370
371
372
373 if(sin.sin_addr.s_addr==INADDR_ANY)
374 sin.sin_addr.s_addr=ip_my_addr();
375
376 if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
377 return -EACCES;
378
379 sk->inuse = 1;
380
381
382 tmp = udp_send(sk, &sin, from, len, flags);
383
384
385 release_sock(sk);
386 return(tmp);
387 }
388
389
390
391
392
393 static int udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
394 unsigned flags)
395 {
396 return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
397 }
398
399
400
401
402
403
404 int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
405 {
406 int err;
407 switch(cmd)
408 {
409 case TIOCOUTQ:
410 {
411 unsigned long amount;
412
413 if (sk->state == TCP_LISTEN) return(-EINVAL);
414 amount = sk->prot->wspace(sk);
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 case TIOCINQ:
424 {
425 struct sk_buff *skb;
426 unsigned long amount;
427
428 if (sk->state == TCP_LISTEN) return(-EINVAL);
429 amount = 0;
430 skb = skb_peek(&sk->receive_queue);
431 if (skb != NULL) {
432
433
434
435
436
437 amount = skb->len;
438 }
439 err=verify_area(VERIFY_WRITE,(void *)arg,
440 sizeof(unsigned long));
441 if(err)
442 return(err);
443 put_fs_long(amount,(unsigned long *)arg);
444 return(0);
445 }
446
447 default:
448 return(-EINVAL);
449 }
450 return(0);
451 }
452
453
454
455
456
457
458
459 int udp_recvfrom(struct sock *sk, unsigned char *to, int len,
460 int noblock, unsigned flags, struct sockaddr_in *sin,
461 int *addr_len)
462 {
463 int copied = 0;
464 struct sk_buff *skb;
465 int er;
466
467
468
469
470
471 if (addr_len)
472 {
473 er=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
474 if(er)
475 return(er);
476 put_fs_long(sizeof(*sin), addr_len);
477 }
478
479 if(sin)
480 {
481 er=verify_area(VERIFY_WRITE, sin, sizeof(*sin));
482 if(er)
483 return(er);
484 }
485
486
487
488
489
490
491 skb=skb_recv_datagram(sk,flags,noblock,&er);
492 if(skb==NULL)
493 return er;
494
495 copied = min(len, skb->len);
496
497
498
499
500
501 skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
502 sk->stamp=skb->stamp;
503
504
505 if (sin)
506 {
507 struct sockaddr_in addr;
508
509 addr.sin_family = AF_INET;
510 addr.sin_port = skb->h.uh->source;
511 addr.sin_addr.s_addr = skb->daddr;
512 memcpy_tofs(sin, &addr, sizeof(*sin));
513 }
514
515 skb_free_datagram(skb);
516 release_sock(sk);
517 return(copied);
518 }
519
520
521
522
523
524 int udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
525 unsigned flags)
526 {
527 return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
528 }
529
530
531 int
532 udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
533 {
534 struct sockaddr_in sin;
535 int er;
536
537 if (addr_len < sizeof(sin))
538 return(-EINVAL);
539
540 er=verify_area(VERIFY_READ, usin, sizeof(sin));
541 if(er)
542 return er;
543
544 memcpy_fromfs(&sin, usin, sizeof(sin));
545 if (sin.sin_family && sin.sin_family != AF_INET)
546 return(-EAFNOSUPPORT);
547 if (sin.sin_addr.s_addr==INADDR_ANY)
548 sin.sin_addr.s_addr=ip_my_addr();
549
550 if(!sk->broadcast && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
551 return -EACCES;
552
553 sk->daddr = sin.sin_addr.s_addr;
554 sk->dummy_th.dest = sin.sin_port;
555 sk->state = TCP_ESTABLISHED;
556 return(0);
557 }
558
559
560 static void
561 udp_close(struct sock *sk, int timeout)
562 {
563 sk->inuse = 1;
564 sk->state = TCP_CLOSE;
565 if (sk->dead) destroy_sock(sk);
566 else release_sock(sk);
567 }
568
569
570
571
572
573
574 int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
575 unsigned long daddr, unsigned short len,
576 unsigned long saddr, int redo, struct inet_protocol *protocol)
577 {
578 struct sock *sk;
579 struct udphdr *uh;
580 unsigned short ulen;
581
582
583
584
585 uh = (struct udphdr *) skb->h.uh;
586
587 ip_statistics.IpInDelivers++;
588
589
590
591
592
593 ulen = ntohs(uh->len);
594
595 if (ulen > len || len < sizeof(*uh) || ulen < sizeof(*uh))
596 {
597 printk("UDP: short packet: %d/%d\n", ulen, len);
598 udp_statistics.UdpInErrors++;
599 kfree_skb(skb, FREE_WRITE);
600 return(0);
601 }
602 len=ulen;
603
604 sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
605 if (sk == NULL)
606 {
607 udp_statistics.UdpNoPorts++;
608 if (ip_chk_addr(daddr) == IS_MYADDR)
609 {
610 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
611 }
612
613
614
615
616 skb->sk = NULL;
617 kfree_skb(skb, FREE_WRITE);
618 return(0);
619 }
620
621 if (uh->check && udp_check(uh, len, saddr, daddr))
622 {
623 printk("UDP: bad checksum.\n");
624 udp_statistics.UdpInErrors++;
625 kfree_skb(skb, FREE_WRITE);
626 return(0);
627 }
628
629 skb->sk = sk;
630 skb->dev = dev;
631 skb->len = len;
632
633
634
635
636
637 skb->daddr = saddr;
638 skb->saddr = daddr;
639
640
641
642
643
644
645 if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
646 {
647 udp_statistics.UdpInErrors++;
648 ip_statistics.IpInDiscards++;
649 ip_statistics.IpInDelivers--;
650 skb->sk = NULL;
651 kfree_skb(skb, FREE_WRITE);
652 release_sock(sk);
653 return(0);
654 }
655 sk->rmem_alloc += skb->mem_len;
656 udp_statistics.UdpInDatagrams++;
657
658
659
660
661
662 skb->len = len - sizeof(*uh);
663 skb_queue_tail(&sk->receive_queue,skb);
664
665
666 if (!sk->dead)
667 sk->data_ready(sk,skb->len);
668
669 release_sock(sk);
670 return(0);
671 }
672
673
674 struct proto udp_prot = {
675 sock_wmalloc,
676 sock_rmalloc,
677 sock_wfree,
678 sock_rfree,
679 sock_rspace,
680 sock_wspace,
681 udp_close,
682 udp_read,
683 udp_write,
684 udp_sendto,
685 udp_recvfrom,
686 ip_build_header,
687 udp_connect,
688 NULL,
689 ip_queue_xmit,
690 ip_retransmit,
691 NULL,
692 NULL,
693 udp_rcv,
694 datagram_select,
695 udp_ioctl,
696 NULL,
697 NULL,
698 ip_setsockopt,
699 ip_getsockopt,
700 128,
701 0,
702 {NULL,},
703 "UDP"
704 };