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