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