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