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