apps/streamer/net_udp.c

Go to the documentation of this file.
00001 /*
00002  * Network initialisation
00003  *
00004  * (C)2004 Alexander Melichenko <alexlp@freemail.ru>
00005  *
00006  * This file consist a portion of code from the UCL Common Code Library (2.4.18)
00007  * Copyright (c) 1998-2001 University College London
00008  *
00009  *  This program is free software: you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation, either version 3 of the License, or
00012  *  (at your option) any later version.
00013  *
00014  *  This program is distributed in the hope that it will be useful,
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00021  */
00022 
00023 
00024 #include <stdio.h>
00025 #include <stdarg.h>
00026 #include <stdint.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <sys/socket.h>
00030 #include <sys/param.h>
00031 #include <unistd.h>
00032 #include <sys/ioctl.h>
00033 #include <netinet/in.h>
00034 #include <net/if.h>
00035 #include <netdb.h>
00036 #include <arpa/inet.h>
00037 //#include <linux/if_packet.h>
00038 #include <linux/if_ether.h>
00039 
00040 #include "str.h"
00041 #include "net_udp.h"
00042 #include "arping.h"
00043 
00044 
00045 int32_t get_src_addr(struct param *p){
00046     struct ifreq ifr;
00047     struct sockaddr_in *sin;
00048     int fd;
00049     int reuse = 1;
00050     
00051     fd = socket(AF_INET, SOCK_DGRAM, 0);
00052     if (fd < 0) {
00053         fprintf(stderr, "Socket error\n");
00054         return -1;
00055     }
00056 
00057     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, sizeof(reuse)) != 0) {
00058         fprintf(stderr, "setsockopt error: SO_REUSEADDR\n");
00059         return -1;
00060     }
00061 #ifdef SO_REUSEPORT
00062     if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *) &reuse,  sizeof(reuse)) != 0) {
00063         fprintf(stderr, "setsockopt error: SO_REUSEPORT\n");
00064         return -1;
00065     }
00066 #endif
00067 
00068     memset(&ifr, 0, sizeof(ifr));
00069     strcpy(ifr.ifr_name, "eth0");
00070     
00071     if(ioctl(fd, SIOCGIFADDR, &ifr) != 0){
00072         fprintf(stderr, "Local address resolution error\n");
00073         return -1;
00074     }
00075 
00076     sin = (struct sockaddr_in*) (ifr.ifr_addr.sa_data+2);
00077     p->src_addr4 = *(struct in_addr*)sin; 
00078     p->src       = inet_ntoa(p->src_addr4);
00079 
00080     close(fd);
00081     
00082     return 0;
00083 }
00084 
00085 
00086 int32_t udp_init4(struct param *p)
00087 {
00088     int reuse = 1;
00089     struct ifreq ifr;
00090     struct sockaddr_in *sin;
00091     in_addr_t src_net, dst_net;
00092 
00093 //fprintf(stderr, "udp_init4\n");
00094     
00095         if(inet_pton(AF_INET, p->dst, &p->dst_addr4) != 1) {
00096                 struct hostent *h = gethostbyname(p->dst);
00097                 if(h == NULL) {
00098                         fprintf(stderr, "Can't resolve IP address for %s\n", p->dst);
00099                         return -1;
00100                 }
00101                 memcpy(&(p->dst_addr4), h->h_addr_list[0], sizeof(p->dst_addr4));
00102         }
00103 
00104     if(!p->raw){
00105         p->fd = socket(AF_INET, SOCK_DGRAM, 0);
00106         if (p->fd < 0) {
00107             fprintf(stderr, "Socket error\n");
00108             return -1;
00109         }
00110         if (setsockopt(p->fd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse, 
00111                 sizeof(reuse)) != 0) {
00112             fprintf(stderr, "setsockopt error: SO_REUSEADDR\n");
00113             return -1;
00114         }
00115 #ifdef SO_REUSEPORT
00116         if (setsockopt(p->fd, SOL_SOCKET, SO_REUSEPORT, (char *) &reuse,
00117              sizeof(reuse)) != 0) {
00118             fprintf(stderr, "setsockopt error: SO_REUSEPORT\n");
00119             return -1;
00120         }
00121 #endif
00122 
00123                 if(IN_MULTICAST(ntohl(p->dst_addr4.s_addr))) {
00124                         struct ip_mreq  imr;
00125 
00126                         imr.imr_multiaddr.s_addr = p->dst_addr4.s_addr;
00127                         imr.imr_interface.s_addr = 0;
00128 
00129                         if(setsockopt(p->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &imr, sizeof(struct ip_mreq)) != 0) {
00130                                 fprintf(stderr, "setsockopt error: IP_ADD_MEMBERSHIP\n");
00131                                 return -1;
00132                         }
00133                         if(setsockopt(p->fd, IPPROTO_IP, IP_MULTICAST_TTL, (char *) &p->ttl, sizeof(p->ttl)) != 0) {
00134                                 fprintf(stderr, "setsockopt error: IP_MULTICAST_TTL\n");
00135                                 return -1;
00136                         }
00137                 }
00138         } else { /* PACKET socket */
00139                 p->fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
00140                 if(p->fd < 0) {
00141                         fprintf(stderr, "Socket error\n");
00142                         return -1;
00143                 }
00144         }
00145 
00146     memset(&ifr, 0, sizeof(ifr));
00147     strcpy(ifr.ifr_name, "eth0");
00148     
00149     if(ioctl(p->fd, SIOCGIFADDR, &ifr) != 0){
00150         fprintf(stderr, "Local address resolution error\n");
00151         return -1;
00152     }
00153     sin = (struct sockaddr_in*) (ifr.ifr_addr.sa_data+2);
00154     p->src_addr4 = *(struct in_addr*)sin; 
00155     p->src    = inet_ntoa(p->src_addr4);
00156     p->eth_index = ifr.ifr_ifindex;
00157 
00158     if(ioctl(p->fd, SIOCGIFNETMASK, &ifr) != 0){
00159         fprintf(stderr, "Local address netmask resolution error\n");
00160         return -1;
00161     }
00162     sin = (struct sockaddr_in*) (ifr.ifr_netmask.sa_data+2);
00163     p->src_netmask4 = *(struct in_addr*)sin; 
00164         
00165     if(ioctl(p->fd, SIOCGIFHWADDR, &ifr) != 0){
00166         fprintf(stderr, "MAC resolution error\n");
00167         return -1;
00168     }
00169     memcpy(p->mac, ifr.ifr_hwaddr.sa_data, 6);
00170 
00171     if (!IN_MULTICAST(ntohl(p->dst_addr4.s_addr))) {
00172         uint32_t dstip;
00173         uint8_t mac[6];
00174         
00175         src_net = p->src_netmask4.s_addr & p->src_addr4.s_addr;
00176         dst_net = p->src_netmask4.s_addr & p->dst_addr4.s_addr;
00177         if(src_net == dst_net){
00178             dstip = p->dst_addr4.s_addr;
00179         } else {
00180         /* send to gateway */
00181             FILE *fp = fopen("/proc/net/route", "r");
00182             unsigned long int d, g, m;
00183             int flgs, ref, use, metric, mtu, win, ir;
00184             int fl=0;
00185             char devname[64];
00186             if (fscanf(fp, "%*[^\n]\n") < 0) { /* Skip the first line. */
00187                /* Empty or missing line, or read error. */
00188                 fprintf(stderr, "Gateway resolution error\n");
00189                 return -1;
00190             }
00191             while (1) {
00192                 int r;
00193                 r = fscanf(fp, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n",
00194                        devname, &d, &g, &flgs, &ref, &use, &metric, &m,
00195                            &mtu, &win, &ir);
00196                 if (r != 11) {
00197                     if ((r < 0) && feof(fp)) { /* EOF with no (nonspace) chars read. */
00198                         break;
00199                     }
00200                     fprintf(stderr, "Gateway resolution error!\n");
00201                     return -1;
00202                 }
00203                 if(!d){
00204                     fl=1;
00205                     break;
00206                 }
00207             }
00208             if(!fl){
00209                 fprintf(stderr, "Gateway resolution error\n");
00210                 return -1;
00211             }
00212             dstip = g;
00213         }
00214         memset(mac, 0, 6);
00215 
00216         if(arping(p->src_addr4, *((struct in_addr*) &dstip), mac) != 0){
00217             fprintf(stderr, "Destination address is not resolved\n");
00218             return -1;
00219         }
00220 
00221         memcpy(p->dst_mac, mac, 6);
00222     }
00223 
00224     return 0;
00225 }
00226 
00227 
00228 void udp_exit4(struct param * p)
00229 {
00230     if(!p->raw){
00231         if (IN_MULTICAST(ntohl(p->dst_addr4.s_addr))) {
00232             struct ip_mreq  imr;
00233             imr.imr_multiaddr.s_addr = p->dst_addr4.s_addr;
00234             imr.imr_interface.s_addr = INADDR_ANY;
00235             if (setsockopt(p->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *) &imr, sizeof(struct ip_mreq)) != 0) {
00236                 fprintf(stderr, "setsockopt IP_DROP_MEMBERSHIP\n");
00237                 abort();
00238             }
00239         }
00240     }
00241     close(p->fd);
00242 }
00243 

Generated on Fri Nov 28 00:06:22 2008 for elphel by  doxygen 1.5.1