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_write
  8. raw_close
  9. raw_init
  10. raw_recvmsg
  11. raw_recvfrom
  12. raw_read

   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 #include <asm/system.h>
  39 #include <asm/segment.h>
  40 #include <linux/types.h>
  41 #include <linux/sched.h>
  42 #include <linux/errno.h>
  43 #include <linux/timer.h>
  44 #include <linux/mm.h>
  45 #include <linux/kernel.h>
  46 #include <linux/fcntl.h>
  47 #include <linux/socket.h>
  48 #include <linux/in.h>
  49 #include <linux/inet.h>
  50 #include <linux/netdevice.h>
  51 #include <linux/mroute.h>
  52 #include <net/ip.h>
  53 #include <net/protocol.h>
  54 #include <linux/skbuff.h>
  55 #include <net/sock.h>
  56 #include <net/icmp.h>
  57 #include <net/udp.h>
  58 #include <net/checksum.h>
  59 
  60 #ifdef CONFIG_IP_MROUTE
  61 struct sock *mroute_socket=NULL;
  62 #endif
  63 
  64 static inline unsigned long min(unsigned long a, unsigned long b)
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66         if (a < b) 
  67                 return(a);
  68         return(b);
  69 }
  70 
  71 
  72 /*
  73  *      Raw_err does not currently get called by the icmp module - FIXME:
  74  */
  75  
  76 void raw_err (int type, int code, unsigned char *header, __u32 daddr,
     /* [previous][next][first][last][top][bottom][index][help] */
  77          __u32 saddr, struct inet_protocol *protocol)
  78 {
  79         struct sock *sk;
  80    
  81         if (protocol == NULL) 
  82                 return;
  83         sk = (struct sock *) protocol->data;
  84         if (sk == NULL) 
  85                 return;
  86 
  87         /* This is meaningless in raw sockets. */
  88         if (type == ICMP_SOURCE_QUENCH) 
  89         {
  90                 if (sk->cong_window > 1) sk->cong_window = sk->cong_window/2;
  91                 return;
  92         }
  93         
  94         if(type == ICMP_PARAMETERPROB)
  95         {
  96                 sk->err = EPROTO;
  97                 sk->error_report(sk);
  98         }
  99 
 100         if(code<13)
 101         {
 102                 sk->err = icmp_err_convert[code & 0xff].errno;
 103                 sk->error_report(sk);
 104         }
 105         
 106         return;
 107 }
 108 
 109 
 110 /*
 111  *      This should be the easiest of all, all we do is
 112  *      copy it into a buffer. All demultiplexing is done
 113  *      in ip.c
 114  */
 115 
 116 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] */
 117 {
 118         /* Now we need to copy this into memory. */
 119         skb->sk = sk;
 120         skb_trim(skb,ntohs(skb->ip_hdr->tot_len));
 121         
 122         skb->h.raw = (unsigned char *) skb->ip_hdr;
 123         skb->dev = dev;
 124         skb->saddr = daddr;
 125         skb->daddr = saddr;
 126         
 127         /* Charge it to the socket. */
 128         
 129         if(sock_queue_rcv_skb(sk,skb)<0)
 130         {
 131                 ip_statistics.IpInDiscards++;
 132                 skb->sk=NULL;
 133                 kfree_skb(skb, FREE_READ);
 134                 return(0);
 135         }
 136 
 137         ip_statistics.IpInDelivers++;
 138         release_sock(sk);
 139         return(0);
 140 }
 141 
 142 /*
 143  *      Send a RAW IP packet.
 144  */
 145 
 146 /*
 147  *      Callback support is trivial for SOCK_RAW
 148  */
 149   
 150 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] */
 151 {
 152         memcpy_fromfs(to, (const unsigned char *)p+offset, fraglen);
 153 }
 154 
 155 /*
 156  *      IPPROTO_RAW needs extra work.
 157  */
 158  
 159 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] */
 160 {
 161         memcpy_fromfs(to, (const unsigned char *)p+offset, fraglen);
 162         if(offset==0)
 163         {
 164                 struct iphdr *iph=(struct iphdr *)to;
 165                 iph->saddr=saddr;
 166                 iph->check=0;
 167                 iph->tot_len=htons(fraglen);    /* This is right as you cant frag
 168                                            RAW packets */
 169                 /*
 170                  *      Deliberate breach of modularity to keep 
 171                  *      ip_build_xmit clean (well less messy).
 172                  */
 173                 iph->id = htons(ip_id_count++);
 174                 iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl);
 175         }
 176 }
 177 
 178 static int raw_sendto(struct sock *sk, const unsigned char *from, 
     /* [previous][next][first][last][top][bottom][index][help] */
 179         int len, int noblock, unsigned flags, struct sockaddr_in *usin, int addr_len)
 180 {
 181         int err;
 182         struct sockaddr_in sin;
 183 
 184         /*
 185          *      Check the flags. Only MSG_DONTROUTE is permitted.
 186          */
 187 
 188         if (flags & MSG_OOB)            /* Mirror BSD error message compatibility */
 189                 return -EOPNOTSUPP;
 190                          
 191         if (flags & ~MSG_DONTROUTE)
 192                 return(-EINVAL);
 193         /*
 194          *      Get and verify the address. 
 195          */
 196 
 197         if (usin) 
 198         {
 199                 if (addr_len < sizeof(sin)) 
 200                         return(-EINVAL);
 201                 memcpy(&sin, usin, sizeof(sin));
 202                 if (sin.sin_family && sin.sin_family != AF_INET) 
 203                         return(-EINVAL);
 204         }
 205         else 
 206         {
 207                 if (sk->state != TCP_ESTABLISHED) 
 208                         return(-EINVAL);
 209                 sin.sin_family = AF_INET;
 210                 sin.sin_port = sk->protocol;
 211                 sin.sin_addr.s_addr = sk->daddr;
 212         }
 213         if (sin.sin_port == 0) 
 214                 sin.sin_port = sk->protocol;
 215   
 216         if (sin.sin_addr.s_addr == INADDR_ANY)
 217                 sin.sin_addr.s_addr = ip_my_addr();
 218 
 219         if (sk->broadcast == 0 && ip_chk_addr(sin.sin_addr.s_addr)==IS_BROADCAST)
 220                 return -EACCES;
 221 
 222         if(sk->ip_hdrincl)
 223         {
 224                 if(len>65535)
 225                         return -EMSGSIZE;
 226                 err=ip_build_xmit(sk, raw_getrawfrag, from, len, sin.sin_addr.s_addr, 0, sk->opt, flags, sin.sin_port, noblock);
 227         }
 228         else
 229         {
 230                 if(len>65535-sizeof(struct iphdr))
 231                         return -EMSGSIZE;
 232                 err=ip_build_xmit(sk, raw_getfrag, from, len, sin.sin_addr.s_addr, 0, sk->opt, flags, sin.sin_port, noblock);
 233         }
 234         return err<0?err:len;
 235 }
 236 
 237 
 238 static int raw_write(struct sock *sk, const unsigned char *buff, int len, int noblock,
     /* [previous][next][first][last][top][bottom][index][help] */
 239            unsigned flags)
 240 {
 241         return(raw_sendto(sk, buff, len, noblock, flags, NULL, 0));
 242 }
 243 
 244 
 245 static void raw_close(struct sock *sk, int timeout)
     /* [previous][next][first][last][top][bottom][index][help] */
 246 {
 247         sk->state = TCP_CLOSE;
 248 #ifdef CONFIG_IP_MROUTE 
 249         if(sk==mroute_socket)
 250         {
 251                 mroute_close(sk);
 252                 mroute_socket=NULL;
 253         }
 254 #endif  
 255 }
 256 
 257 
 258 static int raw_init(struct sock *sk)
     /* [previous][next][first][last][top][bottom][index][help] */
 259 {
 260         return(0);
 261 }
 262 
 263 
 264 /*
 265  *      This should be easy, if there is something there
 266  *      we return it, otherwise we block.
 267  */
 268 
 269 int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
 270      int noblock, int flags,int *addr_len)
 271 {
 272         int copied=0;
 273         struct sk_buff *skb;
 274         int err;
 275         struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
 276 
 277         if (flags & MSG_OOB)
 278                 return -EOPNOTSUPP;
 279                 
 280         if (sk->shutdown & RCV_SHUTDOWN) 
 281                 return(0);
 282 
 283         if (addr_len) 
 284                 *addr_len=sizeof(*sin);
 285 
 286         skb=skb_recv_datagram(sk,flags,noblock,&err);
 287         if(skb==NULL)
 288                 return err;
 289 
 290         copied = min(len, skb->len);
 291         
 292         skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 293         sk->stamp=skb->stamp;
 294 
 295         /* Copy the address. */
 296         if (sin) 
 297         {
 298                 sin->sin_family = AF_INET;
 299                 sin->sin_addr.s_addr = skb->daddr;
 300         }
 301         skb_free_datagram(skb);
 302         release_sock(sk);
 303         return (copied);
 304 }
 305 
 306 
 307 static int raw_recvfrom(struct sock *sk, unsigned char *ubuf, int size, int noblock, unsigned flags,
     /* [previous][next][first][last][top][bottom][index][help] */
 308                 struct sockaddr_in *sa, int *addr_len)
 309 {
 310         struct iovec iov;
 311         struct msghdr msg;
 312 
 313         iov.iov_base = ubuf;
 314         iov.iov_len  = size;
 315 
 316         msg.msg_name      = (void *)sa;
 317         msg.msg_namelen   = 0;
 318         if (addr_len)
 319                 msg.msg_namelen = *addr_len;
 320         msg.msg_accrights = NULL;
 321         msg.msg_iov       = &iov;
 322         msg.msg_iovlen    = 1;
 323 
 324         return raw_recvmsg(sk, &msg, size, noblock, flags, addr_len);
 325 }
 326 
 327 int raw_read (struct sock *sk, unsigned char *buff, int len, int noblock, unsigned flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 328 {
 329         return(raw_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
 330 }
 331 
 332 
 333 struct proto raw_prot = {
 334         raw_close,
 335         raw_read,
 336         raw_write,
 337         raw_sendto,
 338         raw_recvfrom,
 339         ip_build_header,
 340         udp_connect,
 341         NULL,
 342         ip_queue_xmit,
 343         NULL,
 344         NULL,
 345         NULL,
 346         NULL,
 347         datagram_select,
 348 #ifdef CONFIG_IP_MROUTE 
 349         ipmr_ioctl,
 350 #else
 351         NULL,
 352 #endif          
 353         raw_init,
 354         NULL,
 355         ip_setsockopt,
 356         ip_getsockopt,
 357         NULL,
 358         raw_recvmsg,
 359         128,
 360         0,
 361         "RAW",
 362         0, 0,
 363         {NULL,}
 364 };

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