📄 udp.c
字号:
325 return err;
326 memcpy_fromfs(&sin, usin, sizeof(sin));
327 if (sin.sin_family && sin.sin_family != AF_INET)
328 return(-EINVAL);
329 if (sin.sin_port == 0)
330 return(-EINVAL);
331 } else {
332 if (sk->state != TCP_ESTABLISHED) return(-EINVAL);
333 sin.sin_family = AF_INET;
334 sin.sin_port = sk->dummy_th.dest;
335 sin.sin_addr.s_addr = sk->daddr;
336 }
337
338 if(!sk->broadcast && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
339 return -EACCES; /* Must turn broadcast on first */
340 sk->inuse = 1;
341
342 /* Send the packet. */
343 tmp = udp_send(sk, &sin, from, len);
344
345 /* The datagram has been sent off. Release the socket. */
346 release_sock(sk);
347 return(tmp);
348 }
349
350
351 static int
352 udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
353 unsigned flags)
354 {
355 return(udp_sendto(sk, buff, len, noblock, flags, NULL, 0));
356 }
357
358
359 int
360 udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
361 {
362 int err;
363 switch(cmd) {
364 case DDIOCSDBG:
365 {
366 int val;
367
368 if (!suser()) return(-EPERM);
369 err=verify_area(VERIFY_READ, (void *)arg, sizeof(int));
370 if(err)
371 return err;
372 val = get_fs_long((int *)arg);
373 switch(val) {
374 case 0:
375 inet_debug = 0;
376 break;
377 case 1:
378 inet_debug = DBG_UDP;
379 break;
380 default:
381 return(-EINVAL);
382 }
383 }
384 break;
385 case TIOCOUTQ:
386 {
387 unsigned long amount;
388
389 if (sk->state == TCP_LISTEN) return(-EINVAL);
390 amount = sk->prot->wspace(sk)/*/2*/;
391 err=verify_area(VERIFY_WRITE,(void *)arg,
392 sizeof(unsigned long));
393 if(err)
394 return(err);
395 put_fs_long(amount,(unsigned long *)arg);
396 return(0);
397 }
398
399 case TIOCINQ:
400 {
401 struct sk_buff *skb;
402 unsigned long amount;
403
404 if (sk->state == TCP_LISTEN) return(-EINVAL);
405 amount = 0;
406 skb = sk->rqueue;
407 if (skb != NULL) {
408 /*
409 * We will only return the amount
410 * of this packet since that is all
411 * that will be read.
412 */
413 amount = skb->len;
414 }
415 err=verify_area(VERIFY_WRITE,(void *)arg,
416 sizeof(unsigned long));
417 if(err)
418 return(err);
419 put_fs_long(amount,(unsigned long *)arg);
420 return(0);
421 }
422
423 default:
424 return(-EINVAL);
425 }
426 return(0);
427 }
428
429
430 /*
431 * This should be easy, if there is something there we\
432 * return it, otherwise we block.
433 */
434 int
435 udp_recvfrom(struct sock *sk, unsigned char *to, int len,
436 int noblock, unsigned flags, struct sockaddr_in *sin,
437 int *addr_len)
438 {
439 int copied = 0;
440 struct sk_buff *skb;
441 int er;
442
443
444 /*
445 * This will pick up errors that occured while the program
446 * was doing something else.
447 */
448 if (sk->err) {
449 int err;
450
451 err = -sk->err;
452 sk->err = 0;
453 return(err);
454 }
455
456 if (len == 0)
457 return(0);
458 if (len < 0)
459 return(-EINVAL);
460
461 if (addr_len) {
462 er=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
463 if(er)
464 return(er);
465 put_fs_long(sizeof(*sin), addr_len);
466 }
467 if(sin)
468 {
469 er=verify_area(VERIFY_WRITE, sin, sizeof(*sin));
470 if(er)
471 return(er);
472 }
473 er=verify_area(VERIFY_WRITE,to,len);
474 if(er)
475 return er;
476 skb=skb_recv_datagram(sk,flags,noblock,&er);
477 if(skb==NULL)
478 return er;
479 copied = min(len, skb->len);
480
481 /* FIXME : should use udp header size info value */
482 skb_copy_datagram(skb,sizeof(struct udphdr),to,copied);
483
484 /* Copy the address. */
485 if (sin) {
486 struct sockaddr_in addr;
487
488 addr.sin_family = AF_INET;
489 addr.sin_port = skb->h.uh->source;
490 addr.sin_addr.s_addr = skb->daddr;
491 memcpy_tofs(sin, &addr, sizeof(*sin));
492 }
493
494 skb_free_datagram(skb);
495 release_sock(sk);
496 return(copied);
497 }
498
499
500 int
501 udp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
502 unsigned flags)
503 {
504 return(udp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
505 }
506
507
508 int
509 udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
510 {
511 struct sockaddr_in sin;
512 int er;
513
514 if (addr_len < sizeof(sin))
515 return(-EINVAL);
516
517 er=verify_area(VERIFY_READ, usin, sizeof(sin));
518 if(er)
519 return er;
520
521 memcpy_fromfs(&sin, usin, sizeof(sin));
522 if (sin.sin_family && sin.sin_family != AF_INET)
523 return(-EAFNOSUPPORT);
524
525 if(!sk->broadcast && chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
526 return -EACCES; /* Must turn broadcast on first */
527
528 sk->daddr = sin.sin_addr.s_addr;
529 sk->dummy_th.dest = sin.sin_port;
530 sk->state = TCP_ESTABLISHED;
531 return(0);
532 }
533
534
535 static void
536 udp_close(struct sock *sk, int timeout)
537 {
538 sk->inuse = 1;
539 sk->state = TCP_CLOSE;
540 if (sk->dead) destroy_sock(sk);
541 else release_sock(sk);
542 }
543
544
545 /* All we need to do is get the socket, and then do a checksum. */
546 int
547 udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
548 unsigned long daddr, unsigned short len,
549 unsigned long saddr, int redo, struct inet_protocol *protocol)
550 {
551 struct sock *sk;
552 struct udphdr *uh;
553
554 uh = (struct udphdr *) skb->h.uh;
555 sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
556 if (sk == NULL)
557 {
558 if (chk_addr(daddr) == IS_MYADDR)
559 {
560 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, dev);
561 }
562 /*
563 * Hmm. We got an UDP broadcast to a port to which we
564 * don't wanna listen. The only thing we can do now is
565 * to ignore the packet... -FvK
566 */
567 skb->sk = NULL;
568 kfree_skb(skb, FREE_WRITE);
569 return(0);
570 }
571
572 if (uh->check && udp_check(uh, len, saddr, daddr)) {
573 DPRINTF((DBG_UDP, "UDP: bad checksum\n"));
574 skb->sk = NULL;
575 kfree_skb(skb, FREE_WRITE);
576 return(0);
577 }
578
579 skb->sk = sk;
580 skb->dev = dev;
581 skb->len = len;
582
583 /* These are supposed to be switched. */
584 skb->daddr = saddr;
585 skb->saddr = daddr;
586
587
588 /* Charge it to the socket. */
589 if (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)
590 {
591 skb->sk = NULL;
592 kfree_skb(skb, FREE_WRITE);
593 release_sock(sk);
594 return(0);
595 }
596 sk->rmem_alloc += skb->mem_len;
597
598 /* At this point we should print the thing out. */
599 DPRINTF((DBG_UDP, "<< \n"));
600 print_udp(uh);
601
602 /* Now add it to the data chain and wake things up. */
603
604 skb_queue_tail(&sk->rqueue,skb);
605
606 skb->len = len - sizeof(*uh);
607
608 if (!sk->dead)
609 sk->data_ready(sk,skb->len);
610
611 release_sock(sk);
612 return(0);
613 }
614
615
616 struct proto udp_prot = {
617 sock_wmalloc,
618 sock_rmalloc,
619 sock_wfree,
620 sock_rfree,
621 sock_rspace,
622 sock_wspace,
623 udp_close,
624 udp_read,
625 udp_write,
626 udp_sendto,
627 udp_recvfrom,
628 ip_build_header,
629 udp_connect,
630 NULL,
631 ip_queue_xmit,
632 ip_retransmit,
633 NULL,
634 NULL,
635 udp_rcv,
636 datagram_select,
637 udp_ioctl,
638 NULL,
639 NULL,
640 ip_setsockopt,
641 ip_getsockopt,
642 128,
643 0,
644 {NULL,},
645 "UDP"
646 };
647
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -