home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / net / inet / udp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-25  |  14.7 KB  |  647 lines

  1. /*
  2.  * INET        An implementation of the TCP/IP protocol suite for the LINUX
  3.  *        operating system.  INET is implemented using the  BSD Socket
  4.  *        interface as the means of communication with the user level.
  5.  *
  6.  *        The User Datagram Protocol (UDP).
  7.  *
  8.  * Version:    @(#)udp.c    1.0.13    06/02/93
  9.  *
  10.  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  11.  *        Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12.  *
  13.  * Fixes:
  14.  *        Alan Cox    :    verify_area() calls
  15.  *        Alan Cox    :     stopped close while in use off icmp
  16.  *                    messages. Not a fix but a botch that
  17.  *                    for udp at least is 'valid'.
  18.  *        Alan Cox    :    Fixed icmp handling properly
  19.  *        Alan Cox    :     Correct error for oversized datagrams
  20.  *        Alan Cox    :    Tidied select() semantics. 
  21.  *        Alan Cox    :    udp_err() fixed properly, also now 
  22.  *                    select and read wake correctly on errors
  23.  *        Alan Cox    :    udp_send verify_area moved to avoid mem leak
  24.  *        Alan Cox    :    UDP can count its memory
  25.  *        Alan Cox    :    send to an uknown connection causes
  26.  *                    an ECONNREFUSED off the icmp, but
  27.  *                    does NOT close.
  28.  *        Alan Cox    :    Switched to new sk_buff handlers. No more backlog!
  29.  *        Alan Cox    :    Using generic datagram code. Even smaller and the PEEK
  30.  *                    bug no longer crashes it.
  31.  *        Fred Van Kempen    :     Net2e support for sk->broadcast.
  32.  *        Alan Cox    :    Uses skb_free_datagram
  33.  *        Alan Cox    :    Added get/set sockopt support.
  34.  *        Alan Cox    :    Broadcasting without option set returns EACCES.
  35.  *        Alan Cox    :    No wakeup calls. Instead we now use the callbacks.
  36.  *        Alan Cox    :    Use ip_tos and ip_ttl
  37.  *
  38.  *
  39.  *        This program is free software; you can redistribute it and/or
  40.  *        modify it under the terms of the GNU General Public License
  41.  *        as published by the Free Software Foundation; either version
  42.  *        2 of the License, or (at your option) any later version.
  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 "dev.h"
  59. #include "ip.h"
  60. #include "protocol.h"
  61. #include "tcp.h"
  62. #include "skbuff.h"
  63. #include "sock.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
  72. print_udp(struct udphdr *uh)
  73. {
  74.   if (inet_debug != DBG_UDP) return;
  75.  
  76.   if (uh == NULL) {
  77.     printk("(NULL)\n");
  78.     return;
  79.   }
  80.   printk("UDP: source = %d, dest = %d\n", ntohs(uh->source), ntohs(uh->dest));
  81.   printk("     len = %d, check = %d\n", ntohs(uh->len), ntohs(uh->check));
  82. }
  83.  
  84.  
  85. /*
  86.  * This routine is called by the ICMP module when it gets some
  87.  * sort of error condition.  If err < 0 then the socket should
  88.  * be closed and the error returned to the user.  If err > 0
  89.  * it's just the icmp type << 8 | icmp code.  
  90.  * Header points to the ip header of the error packet. We move
  91.  * on past this. Then (as it used to claim before adjustment)
  92.  * header points to the first 8 bytes of the udp header.  We need
  93.  * to find the appropriate port.
  94.  */
  95. void
  96. udp_err(int err, unsigned char *header, unsigned long daddr,
  97.     unsigned long saddr, struct inet_protocol *protocol)
  98. {
  99.   struct udphdr *th;
  100.   struct sock *sk;
  101.   struct iphdr *ip=(struct iphdr *)header;
  102.   
  103.   header += 4*ip->ihl;
  104.   
  105.   th = (struct udphdr *)header;  
  106.    
  107.   DPRINTF((DBG_UDP,"UDP: err(err=%d, header=%X, daddr=%X, saddr=%X, protocl=%X)\n\
  108. sport=%d,dport=%d", err, header, daddr, saddr, protocol, (int)th->source,(int)th->dest));
  109.  
  110.   sk = get_sock(&udp_prot, th->source, daddr, th->dest, saddr);
  111.  
  112.   if (sk == NULL) 
  113.       return;    /* No socket for error */
  114.       
  115.   if (err < 0)        /* As per the calling spec */
  116.   {
  117.       sk->err = -err;
  118.       sk->error_report(sk);        /* User process wakes to see error */
  119.       return;
  120.   }
  121.   
  122.   if (err & 0xff00 ==(ICMP_SOURCE_QUENCH << 8)) {    /* Slow down! */
  123.     if (sk->cong_window > 1) 
  124.         sk->cong_window = sk->cong_window/2;
  125.     return;
  126.   }
  127.  
  128.   sk->err = icmp_err_convert[err & 0xff].errno;
  129.  
  130.   /* It's only fatal if we have connected to them. */
  131.   if (icmp_err_convert[err & 0xff].fatal && sk->state == TCP_ESTABLISHED) {
  132.     sk->err=ECONNREFUSED;
  133.   }
  134.   sk->error_report(sk);
  135. }
  136.  
  137.  
  138. static unsigned short
  139. udp_check(struct udphdr *uh, int len,
  140.       unsigned long saddr, unsigned long daddr)
  141. {
  142.   unsigned long sum;
  143.  
  144.   DPRINTF((DBG_UDP, "UDP: check(uh=%X, len = %d, saddr = %X, daddr = %X)\n",
  145.                                uh, len, saddr, daddr));
  146.  
  147.   print_udp(uh);
  148.  
  149.   __asm__("\t addl %%ecx,%%ebx\n"
  150.       "\t adcl %%edx,%%ebx\n"
  151.       "\t adcl $0, %%ebx\n"
  152.       : "=b"(sum)
  153.       : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256)
  154.       : "cx","bx","dx" );
  155.  
  156.   if (len > 3) {
  157.     __asm__("\tclc\n"
  158.         "1:\n"
  159.         "\t lodsl\n"
  160.         "\t adcl %%eax, %%ebx\n"
  161.         "\t loop 1b\n"
  162.         "\t adcl $0, %%ebx\n"
  163.         : "=b"(sum) , "=S"(uh)
  164.         : "0"(sum), "c"(len/4) ,"1"(uh)
  165.         : "ax", "cx", "bx", "si" );
  166.   }
  167.  
  168.   /* Convert from 32 bits to 16 bits. */
  169.   __asm__("\t movl %%ebx, %%ecx\n"
  170.       "\t shrl $16,%%ecx\n"
  171.       "\t addw %%cx, %%bx\n"
  172.       "\t adcw $0, %%bx\n"
  173.       : "=b"(sum)
  174.       : "0"(sum)
  175.       : "bx", "cx");
  176.  
  177.   /* Check for an extra word. */
  178.   if ((len & 2) != 0) {
  179.     __asm__("\t lodsw\n"
  180.         "\t addw %%ax,%%bx\n"
  181.         "\t adcw $0, %%bx\n"
  182.         : "=b"(sum), "=S"(uh)
  183.         : "0"(sum) ,"1"(uh)
  184.         : "si", "ax", "bx");
  185.   }
  186.  
  187.   /* Now check for the extra byte. */
  188.   if ((len & 1) != 0) {
  189.     __asm__("\t lodsb\n"
  190.         "\t movb $0,%%ah\n"
  191.         "\t addw %%ax,%%bx\n"
  192.         "\t adcw $0, %%bx\n"
  193.         : "=b"(sum)
  194.         : "0"(sum) ,"S"(uh)
  195.         : "si", "ax", "bx");
  196.   }
  197.  
  198.   /* We only want the bottom 16 bits, but we never cleared the top 16. */
  199.   return((~sum) & 0xffff);
  200. }
  201.  
  202.  
  203. static void
  204. udp_send_check(struct udphdr *uh, unsigned long saddr, 
  205.            unsigned long daddr, int len, struct sock *sk)
  206. {
  207.   uh->check = 0;
  208.   if (sk && sk->no_check) 
  209.       return;
  210.   uh->check = udp_check(uh, len, saddr, daddr);
  211.   if (uh->check == 0) uh->check = 0xffff;
  212. }
  213.  
  214.  
  215. static int
  216. udp_send(struct sock *sk, struct sockaddr_in *sin,
  217.      unsigned char *from, int len)
  218. {
  219.   struct sk_buff *skb;
  220.   struct device *dev;
  221.   struct udphdr *uh;
  222.   unsigned char *buff;
  223.   unsigned long saddr;
  224.   int size, tmp;
  225.   int err;
  226.   
  227.   DPRINTF((DBG_UDP, "UDP: send(dst=%s:%d buff=%X len=%d)\n",
  228.         in_ntoa(sin->sin_addr.s_addr), ntohs(sin->sin_port),
  229.         from, len));
  230.  
  231.   err=verify_area(VERIFY_READ, from, len);
  232.   if(err)
  233.       return(err);
  234.  
  235.   /* Allocate a copy of the packet. */
  236.   size = sizeof(struct sk_buff) + sk->prot->max_header + len;
  237.   skb = sk->prot->wmalloc(sk, size, 0, GFP_KERNEL);
  238.   if (skb == NULL) return(-ENOMEM);
  239.  
  240.   skb->mem_addr = skb;
  241.   skb->mem_len  = size;
  242.   skb->sk       = NULL;    /* to avoid changing sk->saddr */
  243.   skb->free     = 1;
  244.   skb->arp      = 0;
  245.  
  246.   /* Now build the IP and MAC header. */
  247.   buff = skb->data;
  248.   saddr = 0;
  249.   dev = NULL;
  250.   DPRINTF((DBG_UDP, "UDP: >> IP_Header: %X -> %X dev=%X prot=%X len=%d\n",
  251.             saddr, sin->sin_addr.s_addr, dev, IPPROTO_UDP, skb->mem_len));
  252.   tmp = sk->prot->build_header(skb, saddr, sin->sin_addr.s_addr,
  253.                    &dev, IPPROTO_UDP, sk->opt, skb->mem_len,sk->ip_tos,sk->ip_ttl);
  254.   skb->sk=sk;    /* So memory is freed correctly */
  255.                 
  256.   if (tmp < 0 ) {
  257.     sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
  258.     return(tmp);
  259.   }
  260.   buff += tmp;
  261.   saddr = dev->pa_addr;
  262.   DPRINTF((DBG_UDP, "UDP: >> MAC+IP len=%d\n", tmp));
  263.  
  264.   skb->len = tmp + sizeof(struct udphdr) + len;    /* len + UDP + IP + MAC */
  265.   skb->dev = dev;
  266. #ifdef OLD
  267.   /*
  268.    * This code used to hack in some form of fragmentation.
  269.    * I removed that, since it didn't work anyway, and it made the
  270.    * code a bad thing to read and understand. -FvK
  271.    */
  272.   if (len > dev->mtu) {
  273. #else
  274.   if (skb->len > 4095)
  275.   {
  276. #endif    
  277.     printk("UDP: send: length %d > mtu %d (ignored)\n", len, dev->mtu);
  278.     sk->prot->wfree(sk, skb->mem_addr, skb->mem_len);
  279.     return(-EMSGSIZE);
  280.   }
  281.  
  282.   /* Fill in the UDP header. */
  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.   /* Copy the user data. */
  290.   memcpy_fromfs(buff, from, len);
  291.  
  292.   /* Set up the UDP checksum. */
  293.   udp_send_check(uh, saddr, sin->sin_addr.s_addr, skb->len - tmp, sk);
  294.  
  295.   /* Send the datagram to the interface. */
  296.   sk->prot->queue_xmit(sk, dev, skb, 1);
  297.  
  298.   return(len);
  299. }
  300.  
  301.  
  302. static int
  303. udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
  304.        unsigned flags, struct sockaddr_in *usin, int addr_len)
  305. {
  306.   struct sockaddr_in sin;
  307.   int tmp;
  308.   int err;
  309.  
  310.   DPRINTF((DBG_UDP, "UDP: sendto(len=%d, flags=%X)\n", len, flags));
  311.  
  312.   /* Check the flags. */
  313.   if (flags) 
  314.       return(-EINVAL);
  315.   if (len < 0) 
  316.       return(-EINVAL);
  317.   if (len == 0) 
  318.       return(0);
  319.  
  320.   /* Get and verify the address. */
  321.   if (usin) {
  322.     if (addr_len < sizeof(sin)) return(-EINVAL);
  323.     err=verify_area(VERIFY_READ, usin, sizeof(sin));
  324.     if(err)
  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.