"Fossies" - the Fresh Open Source Software Archive

Member "dosemu-1.4.0/src/dosext/net/net/libpacket.c" (4 May 2007, 5099 Bytes) of package /linux/misc/old/dosemu-1.4.0.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "libpacket.c" see the Fossies "Dox" file reference documentation.

    1 /* 
    2  * All modifications in this file to the original code are
    3  * (C) Copyright 1992, ..., 2007 the "DOSEMU-Development-Team".
    4  *
    5  * for details see file COPYING.DOSEMU in the DOSEMU distribution
    6  */
    7 
    8 /*
    9  *  SOCK_PACKET support.
   10  *  Placed under the GNU LGPL.
   11  *
   12  *  First cut at a library of handy support routines. Comments, additions
   13  *  and bug fixes greatfully received.
   14  *
   15  *  (c) 1994 Alan Cox   iiitac@pyr.swan.ac.uk   GW4PTS@GB7SWN
   16  */
   17 #include <stdio.h>
   18 #include <unistd.h>
   19 #include <string.h>
   20 #include <stdlib.h>
   21 #include <fcntl.h>
   22 #include <errno.h>
   23 #include <sys/socket.h>
   24 #include <sys/ioctl.h>
   25 #include <sys/stat.h>
   26 #include <net/if.h>
   27 #include <netinet/in.h>
   28 #include "Linux/if_tun.h"
   29 #include <netinet/if_ether.h>
   30 #include <netpacket/packet.h>
   31 #include <net/ethernet.h>
   32 
   33 #include "emu.h"
   34 #include "priv.h"
   35 #include "libpacket.h"
   36 #include "dosnet.h"
   37 #include "pktdrvr.h"
   38 
   39 static int tun_alloc(char *dev);
   40 
   41 static unsigned short int DosnetID = 0xffff;
   42 char local_eth_addr[6] = {0,0,0,0,0,0};
   43 
   44 /* Should return a unique ID corresponding to this invocation of
   45    dosemu not clashing with other dosemus. We use a random value and
   46    hope for the best.
   47    */
   48 
   49 int GetDosnetID(void)
   50 {  
   51     return DosnetID;
   52 }
   53 
   54 void GenerateDosnetID(void)
   55 {  
   56     DosnetID = DOSNET_TYPE_BASE + (rand() & 0xff);
   57     pd_printf("Assigned DosnetID=%x\n", DosnetID);
   58 }
   59 
   60 /*
   61  *  Obtain a file handle on a raw ethernet type. In actual fact
   62  *  you can also request the dummy types for AX.25 or 802.3 also
   63  *
   64  *  -1 indicates an error
   65  *  0  or higher is a file descriptor which we have set non blocking
   66  *
   67  *  WARNING: It is ok to listen to a service the system is using (eg arp)
   68  *  but don't try and run a user mode stack on the same service or all
   69  *  hell will break loose - unless you use virtual TCP/IP (dosnet).
   70  */
   71 
   72 int OpenNetworkLink(char *name, unsigned short netid)
   73 {
   74     PRIV_SAVE_AREA
   75     int s, proto, ret;
   76     struct ifreq req;
   77     struct sockaddr_ll addr;
   78 
   79     if (config.vnet == VNET_TYPE_TAP) {
   80         receive_mode = 6;
   81         return tun_alloc(name);
   82     }
   83 
   84     proto = htons(netid);
   85 
   86     enter_priv_on();
   87     s = socket(PF_PACKET, SOCK_RAW, proto);
   88     leave_priv_setting();
   89     if (s < 0) {
   90         if (errno == EPERM) error("Must be root for direct NIC access\n");
   91         return -1;
   92     }
   93     fcntl(s, F_SETFL, O_NDELAY);
   94     strcpy(req.ifr_name, name);
   95     if (ioctl(s, SIOCGIFINDEX, &req) < 0) {
   96         close(s);
   97         return -1;
   98     }
   99     addr.sll_family = AF_PACKET;
  100     addr.sll_protocol = proto;
  101     addr.sll_ifindex = req.ifr_ifindex;
  102     if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  103         pd_printf("OpenNetwork: could not bind socket: %s\n",
  104             strerror(errno));
  105         close(s);
  106         return -1;
  107     }
  108 
  109     enter_priv_on();
  110     ret = ioctl(s, SIOCGIFFLAGS, &req);
  111     leave_priv_setting();
  112     if (ret < 0) {
  113         close(s);
  114         return -1;
  115     }
  116 
  117     receive_mode = (req.ifr_flags & IFF_PROMISC) ? 6 :
  118         ((req.ifr_flags & IFF_BROADCAST) ? 3 : 2);
  119 
  120     return s;
  121 }
  122 
  123 /*
  124  *  Close a file handle to a raw packet type.
  125  */
  126 
  127 void 
  128 CloseNetworkLink(int sock)
  129 {
  130     close(sock);
  131 }
  132 
  133 /*
  134  *  Handy support routines.
  135  */
  136 
  137 /*
  138  *  NET2 or NET3 - work for both.
  139  *      (NET3 is valid for all kernels > 1.3.38)
  140  */
  141 #define NET3
  142 
  143 /*
  144  *  Obtain the hardware address of an interface.
  145  *  addr should be a buffer of 8 bytes or more.
  146  *
  147  *  Return:
  148  *  0   Success, buffer holds data.
  149  *  -1  Error.
  150  */
  151 
  152 int 
  153 GetDeviceHardwareAddress(char *device, char *addr)
  154 {  
  155     if (config.vnet == VNET_TYPE_DSN || config.vnet == VNET_TYPE_TAP) {
  156         /* This routine is totally local; doesn't make 
  157            request to actual device. */
  158         int i;
  159         memcpy(local_eth_addr, DOSNET_FAKED_ETH_ADDRESS, 6);
  160         *(unsigned short int *)&(local_eth_addr[2]) = DosnetID;
  161 
  162         memcpy(addr, local_eth_addr, 6);
  163 
  164         pd_printf("Assigned Ethernet Address = ");
  165         for (i=0; i < 6; i++)
  166             pd_printf("%02x:", local_eth_addr[i] & 0xff);
  167         pd_printf("\n");
  168         }
  169     else {
  170         int s = socket(AF_INET, SOCK_DGRAM, 0);
  171         struct ifreq req;
  172         int err;
  173 
  174         strcpy(req.ifr_name, device);
  175 
  176         err = ioctl(s, SIOCGIFHWADDR, &req);  
  177         close(s);
  178         if (err == -1)
  179             return err;
  180 #ifdef NET3    
  181         memcpy(addr, req.ifr_hwaddr.sa_data,8);
  182 #else
  183         memcpy(addr, req.ifr_hwaddr, 8);
  184 #endif  
  185     }
  186     return 0;
  187 }
  188 
  189 /*
  190  *  Obtain the maximum packet size on an interface.
  191  *
  192  *  Return:
  193  *  >0  Return is the mtu of the interface
  194  *  -1  Error.
  195  */
  196 
  197 int 
  198 GetDeviceMTU(char *device)
  199 {
  200     int s = socket(AF_INET, SOCK_DGRAM, 0);
  201     struct ifreq req;
  202     int err;
  203 
  204     strcpy(req.ifr_name, device);
  205 
  206     err = ioctl(s, SIOCGIFMTU, &req);
  207     close(s);
  208     if (err < 0)
  209         return -1;
  210     return req.ifr_mtu;
  211 }
  212 
  213 
  214 static int tun_alloc(char *dev)
  215 {
  216       struct ifreq ifr;
  217       int fd, err;
  218 
  219       if( (fd = open("/dev/net/tun", O_RDWR)) < 0 )
  220          return -1;
  221 
  222       memset(&ifr, 0, sizeof(ifr));
  223 
  224       /* Flags: IFF_TUN   - TUN device (no Ethernet headers)
  225        *        IFF_TAP   - TAP device
  226        *
  227        *        IFF_NO_PI - Do not provide packet information
  228        */
  229       ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
  230       if( *dev )
  231          strncpy(ifr.ifr_name, dev, IFNAMSIZ);
  232 
  233       if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
  234          close(fd);
  235          return err;
  236       }
  237       strcpy(dev, ifr.ifr_name);
  238 
  239       return fd;
  240 }