root/net/ipv4/raw.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. min
  2. raw_err
  3. raw_rcv
  4. raw_getfrag
  5. raw_getrawfrag
  6. raw_sendto
  7. raw_sendmsg
  8. raw_close
  9. raw_init
  10. raw_recvmsg

   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  *              RAW - implementation of IP "raw" sockets.
   7  *
   8  * Version:     @(#)raw.c       1.0.4   05/25/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() fixed up
  15  *              Alan Cox        :       ICMP error handling
  16  *              Alan Cox        :       EMSGSIZE if you send too big a packet
  17  *              Alan Cox        :       Now uses generic datagrams and shared skbuff
  18  *                                      library. No more peek crashes, no more backlogs
  19  *              Alan Cox        :       Checks sk->broadcast.
  20  *              Alan Cox        :       Uses skb_free_datagram/skb_copy_datagram
  21  *              Alan Cox        :       Raw passes ip options too
  22  *              Alan Cox        :       Setsocketopt added
  23  *              Alan Cox        :       Fixed error return for broadcasts
  24  *              Alan Cox        :       Removed wake_up calls
  25  *              Alan Cox        :       Use ttl/tos
  26  *              Alan Cox        :       Cleaned up old debugging
  27  *              Alan Cox        :       Use new kernel side addresses
  28  *      Arnt Gulbrandsen        :       Fixed MSG_DONTROUTE in raw sockets.
  29  *              Alan Cox        :       BSD style RAW socket demultiplexing.
  30  *              Alan Cox        :       Beginnings of mrouted support.
  31  *              Alan Cox        :       Added IP_HDRINCL option.
  32  *
  33  *              This program is free software; you can redistribute it and/or
  34  *              modify it under the terms of the GNU General Public License
  35  *              as published by the Free Software Foundation; either version
  36  *              2 of the License, or (at your option) any later version.
  37  */
  38  
  39 #include <linux/config.h> 
  40 #include <asm/system.h>
  41 #include <asm/segment.h>
  42 #include <linux/types.h>
  43 #include <linux/sched.h>
  44 #include <linux/errno.h>
  45 #include <linux/timer.h>
  46 #include <linux/mm.h>
  47 #include <linux/kernel.h>
  48 #include <linux/fcntl.h>
  49 #include <linux/socket.h>
  50 #include <linux/in.h>
  51 #include <linux/inet.h>
  52 #include <linux/netdevice.h>
  53 #include <linux/mroute.h>
  54 #include <net/ip.h>
  55 #include <net/protocol.h>
  56 #include <linux/skbuff.h>
  57 #include <net/sock.h>
  58 #include <net/icmp.h>
  59 #include <net/udp.h>
  60 #include <net/checksum.h>
  61 
  62 #ifdef CONFIG_IP_MROUTE
  63 struct sock *mroute_socket=NULL;
  64 #endif
  65 
  66 static inline unsigned long min(unsigned long a, unsigned long b)
     /* [previous][next][first][last][top][bottom][index][help] */
  67 {
  68         if (a < b) 
  69                 return(a);
  70         return(b);
  71 }
  72 
  73 
  74 /*
  75  *      Raw_err does not currently get called by the icmp module - FIXME:
  76  */
  77  
  78 void raw_err (int type, int code, unsigned char *header, __u32 daddr,
     /* [previous][next][first][last][top][bottom][index][help] */
  79          __u32 saddr, struct inet_protocol *protocol)
  80 {
  81         struct sock *sk;
  82    
  83         if (protocol == NULL) 
  84                 return;
  85         sk = (struct sock *) protocol->data;
  86         if (sk == NULL) 
  87                 return;
  88 
  89         /* This is meaningless in raw sockets. */
  90         if (type == ICMP_SOURCE_QUENCH) 
  91         {
  92                 if (sk->cong_window > 1) sk->cong_window = sk->cong_window/2;
  93                 return;
  94         }
  95         
  96         if(type == ICMP_PARAMETERPROB)
  97         {
  98                 sk->err = EPROTO;
  99                 sk->error_report(sk);
 100         }
 101 
 102         if(code<13)
 103         {
 104                 sk->err = icmp_err_convert[code & 0xff].errno;
 105                 sk->error_report(sk);
 106         }
 107         
 108         return;
 109 }
 110 
 111 
 112 /*
 113  *      This should be the easiest of all, all we do is
 114  *      copy it into a buffer. All demultiplexing is done
 115  *      in ip.c
 116  */
 117 
 118 int raw_rcv(struct sock *sk, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 119 {
 120         /* Now we need to copy this into memory. */
 121         skb->sk = sk;
 122         skb_trim(skb,ntohs(skb->ip_hdr->tot_len));
 123         
 124         skb->h.raw = (unsigned char *) skb->ip_hdr;
 125         skb->dev = dev;
 126         skb->saddr = daddr;
 127         skb->daddr = saddr;
 128 
 129 #if 0   
 130         /*
 131          *      For no adequately explained reasons BSD likes to mess up the header of
 132          *      the received frame. 
 133          */
 134          
 135         if(sk->bsdism)
 136                 skb->ip_hdr->tot_len=ntohs(skb->ip_hdr->tot_len-4*skb->ip_hdr->ihl);
 137 #endif
 138         
 139         /* Charge it to the socket. */
 140         
 141         if(sock_queue_rcv_skb(sk,skb)<0)
 142         {
 143                 ip_statistics.IpInDiscards++;
 144                 skb->sk=NULL;
 145                 kfree_skb(skb, FREE_READ);
 146                 return(0);
 147         }
 148 
 149         ip_statistics.IpInDelivers++;
 150         release_sock(sk);
 151         return(0);
 152 }
 153 
 154 /*
 155  *      Send a RAW IP packet.
 156  */
 157 
 158 /*
 159  *      Callback support is trivial for SOCK_RAW
 160  */
 161   
 162 static void raw_getfrag(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
     /* [previous][next][first][last][top][bottom][index][help] */
 163 {
 164         memcpy_fromfs(to, (const unsigned char *)p+offset, fraglen);
 165 }
 166 
 167 /*
 168  *      IPPROTO_RAW needs extra work.
 169  */
 170  
 171 static void raw_getrawfrag(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         memcpy_fromfs(to, (const unsigned char *)p+offset, fraglen);
 174         if(offset==0)
 175         {
 176                 struct iphdr *iph=(struct iphdr *)to;
 177                 iph->saddr=saddr;
 178                 iph->check=0;
 179                 iph->tot_len=htons(fraglen);    /* This is right as you cant frag
 180                                            RAW packets */
 181                 /*
 182                  *      Deliberate breach of modularity to keep 
 183                  *      ip_build_xmit clean (well less messy).
 184                  */
 185                 iph->id = htons(ip_id_count++);
 186                 iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl);
 187         }
 188 }
 189 
 190 static int raw_sendto(struct sock *sk, const unsigned char *from, 
     /* [previous][next][first][last][top][bottom][index][help] */
 191         int len, int noblock, unsigned flags, struct sockaddr_in *usin, int addr_len)
 192 {
 193         int err;
 194         struct sockaddr_in sin;
 195 
 196         /*
 197          *      Check the flags. Only MSG_DONTROUTE is permitted.
 198          */
 199 
 200         if (flags & MSG_OOB)            /* Mirror BSD error message compatibility */
 201                 return -EOPNOTSUPP;
 202                          
 203         if (flags & ~MSG_DONTROUTE)
 204                 return(-EINVAL);
 205         /*
 206          *      Get and verify the address. 
 207          */
 208 
 209         if (usin) 
 210         {
 211                 if (addr_len < sizeof(sin)) 
 212                         return(-EINVAL);
 213                 memcpy(&sin, usin, sizeof(sin));
 214                 if (sin.sin_family && sin.sin_family != AF_INET) 
 215                         return(-EINVAL);
 216         }
 217         else 
 218         {
 219                 if (sk->state != TCP_ESTABLISHED) 
 220                         return(-EINVAL);
 221                 sin.sin_family = AF_INET;
 222                 sin.sin_port = sk->protocol;
 223                 sin.sin_addr.s_addr = sk->daddr;
 224         }
 225         if (sin.sin_port == 0) 
 226                 sin.sin_port = sk->protocol;
 227   
 228         if (sin.sin_addr.s_addr == INADDR_ANY)
 229                 sin.sin_addr.s_addr = ip_my_addr();
 230 
 231         if (sk->broadcast == 0 && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
 232                 return -EACCES;
 233 
 234         if(sk->ip_hdrincl)
 235         {
 236                 if(len>65535)
 237                         return -EMSGSIZE;
 238                 err=ip_build_xmit(sk, raw_getrawfrag, from, len, sin.sin_addr.s_addr, 0, sk->opt, flags, sin.sin_port, noblock);
 239         }
 240         else
 241         {
 242                 if(len>65535-sizeof(struct iphdr))
 243                         return -EMSGSIZE;
 244                 err=ip_build_xmit(sk, raw_getfrag, from, len, sin.sin_addr.s_addr, 0, sk->opt, flags, sin.sin_port, noblock);
 245         }
 246         return err<0?err:len;
 247 }
 248 
 249 /*
 250  *      Temporary
 251  */
 252  
 253 static int raw_sendmsg(struct sock *sk, struct msghdr *msg, int len, int noblock, 
     /* [previous][next][first][last][top][bottom][index][help] */
 254         int flags)
 255 {
 256         if(msg->msg_iovlen==1)
 257                 return raw_sendto(sk,msg->msg_iov[0].iov_base,len, noblock, flags, msg->msg_name, msg->msg_namelen);
 258         else
 259         {
 260                 /*
 261                  *      For awkward cases we linearise the buffer first. In theory this is only frames
 262                  *      whose iovec's don't split on 4 byte boundaries, and soon encrypted stuff (to keep
 263                  *      skip happy). We are a bit more general about it.
 264                  */
 265                  
 266                 unsigned char *buf;
 267                 int fs;
 268                 int err;
 269                 if(len>65515)
 270                         return -EMSGSIZE;
 271                 buf=kmalloc(len, GFP_KERNEL);
 272                 if(buf==NULL)
 273                         return -ENOBUFS;
 274                 memcpy_fromiovec(buf, msg->msg_iov, len);
 275                 fs=get_fs();
 276                 set_fs(get_fs());
 277                 err=raw_sendto(sk,buf,len, noblock, flags, msg->msg_name, msg->msg_namelen);
 278                 set_fs(fs);
 279                 kfree_s(buf,len);
 280                 return err;
 281         }
 282 }
 283 
 284 static void raw_close(struct sock *sk, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 285 {
 286         sk->state = TCP_CLOSE;
 287 #ifdef CONFIG_IP_MROUTE 
 288         if(sk==mroute_socket)
 289         {
 290                 mroute_close(sk);
 291                 mroute_socket=NULL;
 292         }
 293 #endif  
 294 }
 295 
 296 
 297 static int raw_init(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 298 {
 299         return(0);
 300 }
 301 
 302 
 303 /*
 304  *      This should be easy, if there is something there
 305  *      we return it, otherwise we block.
 306  */
 307 
 308 int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 309      int noblock, int flags,int *addr_len)
 310 {
 311         int copied=0;
 312         struct sk_buff *skb;
 313         int err;
 314         struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
 315 
 316         if (flags & MSG_OOB)
 317                 return -EOPNOTSUPP;
 318                 
 319         if (sk->shutdown & RCV_SHUTDOWN) 
 320                 return(0);
 321 
 322         if (addr_len) 
 323                 *addr_len=sizeof(*sin);
 324 
 325         skb=skb_recv_datagram(sk,flags,noblock,&err);
 326         if(skb==NULL)
 327                 return err;
 328 
 329         copied = min(len, skb->len);
 330         
 331         skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 332         sk->stamp=skb->stamp;
 333 
 334         /* Copy the address. */
 335         if (sin) 
 336         {
 337                 sin->sin_family = AF_INET;
 338                 sin->sin_addr.s_addr = skb->daddr;
 339         }
 340         skb_free_datagram(skb);
 341         release_sock(sk);
 342         return (copied);
 343 }
 344 
 345 
 346 struct proto raw_prot = {
 347         raw_close,
 348         ip_build_header,
 349         udp_connect,
 350         NULL,
 351         ip_queue_xmit,
 352         NULL,
 353         NULL,
 354         NULL,
 355         NULL,
 356         datagram_select,
 357 #ifdef CONFIG_IP_MROUTE 
 358         ipmr_ioctl,
 359 #else
 360         NULL,
 361 #endif          
 362         raw_init,
 363         NULL,
 364         ip_setsockopt,
 365         ip_getsockopt,
 366         raw_sendmsg,
 367         raw_recvmsg,
 368         NULL,           /* No special bind */
 369         128,
 370         0,
 371         "RAW",
 372         0, 0,
 373         {NULL,}
 374 };

/* [previous][next][first][last][top][bottom][index][help] */