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