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