libcyberradio  22.01.24
TransmitSocket.cpp
1 /***************************************************************************
2  * \file TransmitSocket.cpp
3  *
4  * \brief NDR651 transmitter socket class.
5  *
6  * \author NH
7  * \copyright Copyright (c) 2015-2021 CyberRadio Solutions, Inc.
8  *
9  */
10 
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <linux/if_ether.h>
14 #include <netinet/ip.h>
15 #include <netinet/udp.h>
16 #include <arpa/inet.h>
17 #include <linux/filter.h>
18 #include "LibCyberRadio/NDR651/TransmitSocket.h"
19 #include <netpacket/packet.h>
20 #include <net/ethernet.h>
21 #include <net/if.h>
22 #include <sys/types.h>
23 #include <sys/ioctl.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <ifaddrs.h>
27 #include <iostream>
28 
29 
30 namespace LibCyberRadio
31 {
32  namespace NDR651
33  {
34 
35  TransmitSocket::TransmitSocket(const std::string& ifname, unsigned int sport) :
36  _isBroadcast(true),
37  _txBytes(0),
38  _sendCount(0),
39  _byteCount(0),
40  _isRaw(geteuid()==0),
41  _ifname(ifname),
42  _sport(sport)
43  {
44  // TODO Auto-generated constructor stub
45  //_ifname = ifname;
46  //_usingRingBuffer = useRingBuffer;
47  _makeSocket();
48  }
49 
51  // TODO Auto-generated destructor stub
52  }
53 
54  bool TransmitSocket::_makeRawSocket() {
55  //~ std::cout << "\t..._makeRawSocket\n";
56  int optval; /* flag value for setsockopt */
57  int rv;
58  struct sockaddr_ll addr; /* link layer address */
59 
60  //std::cout << "Creating socket...";
61  _sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP));
62  //if (_sockfd< 0)
63  //std::cout << "ERROR?";
64  //else
65  //std::cout << "success!";
66  //std::cout << std::endl;
67 
68  optval = 1;
69  setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR,
70  (const void *)&optval , sizeof(int));
71 
72  /* bind the socket */
73  memset(&addr,0,sizeof(addr));
74  addr.sll_family=AF_PACKET;
75  addr.sll_protocol=htons(ETH_P_IP);
76  addr.sll_ifindex=if_nametoindex(_ifname.c_str());
77 
78  //std::cout << "Binding socket...";
79  if (bind(_sockfd,(struct sockaddr*)&addr,sizeof(addr))) {
80  //std::cerr << "ERROR?";
81  } else {
82  //std::cout << "success!";
83  }
84  //std::cout << std::endl;
85  return _sockfd>0;
86  }
87 
88  bool TransmitSocket::_makeUdpSocket() {
89  //~ std::cout << "\t..._makeUdpSocket\n";
90  int rv;
91  struct sockaddr_in serveraddr; /* server's addr */
92  struct ifreq ifr;
93  char str[INET_ADDRSTRLEN];
94 
95  _sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
96 
97  // get interface's IP address
98  ifr.ifr_addr.sa_family = AF_INET;
99  strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
100  ioctl(_sockfd, SIOCGIFADDR, &ifr);
101 
102  int optval = 1;
103  /*
104  * Set the "resuse address" flag
105  */
106  //~ rv = setsockopt(_sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval, sizeof(int));
107 
108  /*
109  * build the server's Internet address
110  */
111  memset((char *) &serveraddr, 0, sizeof(serveraddr));
112  serveraddr.sin_family = AF_INET;
113  serveraddr.sin_port = htons((unsigned short)_sport);
114  serveraddr.sin_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
115 
116  /*
117  * bind: associate the parent socket with a port
118  */
119  //~ std::cout << "Binding socket...";
120  //~ if (bind(_sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0)
121  //~ std::cerr << "ERROR?";
122  //~ else
123  //~ std::cout << "success!";
124 
125  /*
126  * Set destination address
127  */
128  if (_isBroadcast||true) {
129  rv = setsockopt(_sockfd, SOL_SOCKET, SO_BROADCAST, (const void *)&optval, sizeof(int) );
130  //std::cout << "setsockopt SO_BROADCAST: " << ((rv==0)?"Success":"Fail") << std::endl;
131 
132  struct ifaddrs *ifap, *ifa;
133  struct sockaddr_in *sa;
134  char *addr;
135  std::string retString;
136  getifaddrs (&ifap);
137  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
138  if ( strcmp(ifa->ifa_name,_ifname.c_str())==0 ){
139  if (ifa->ifa_addr->sa_family==AF_INET) {
140  sa = (struct sockaddr_in *) ifa->ifa_ifu.ifu_broadaddr;
141  sa->sin_port = htons(_sport);
142  addr = inet_ntoa(sa->sin_addr);
143  rv = connect(_sockfd, (struct sockaddr *)sa, sizeof(sockaddr_in));
144  //~ std::cout << "Connect: " << ((rv==0)?"Success":"Fail") << std::endl;
145  break;
146  }
147  }
148  }
149  freeifaddrs(ifap);
150 
151  } else {
152  std::cerr << "I NEED A DESTINATION ADDRESS" << std::endl;
153  }
154 
155  //~ rv = setsockopt(_sockfd, SOL_SOCKET, SO_BINDTODEVICE, _ifname.c_str(), IF_NAMESIZE);
156  return _sockfd>0;
157  }
158 
159  bool TransmitSocket::_makeSocket() {
160  //~ std::cout << "_makeSocket...\n";
161  if (_isRaw) {
162  return _makeRawSocket();
163  } else {
164  return _makeUdpSocket();
165  }
166  }
167 
169  // Source MAC Address
170  char macstring[32];
171  struct ifreq ifr;
172  memset(&ifr, 0x00, sizeof(ifr));
173  strcpy(ifr.ifr_name, _ifname.c_str());
174  ioctl(_sockfd, SIOCGIFHWADDR, &ifr);
175  sprintf(macstring, "%02x:%02x:%02x:%02x:%02x:%02x",
176  (unsigned char)ifr.ifr_hwaddr.sa_data[0],
177  (unsigned char)ifr.ifr_hwaddr.sa_data[1],
178  (unsigned char)ifr.ifr_hwaddr.sa_data[2],
179  (unsigned char)ifr.ifr_hwaddr.sa_data[3],
180  (unsigned char)ifr.ifr_hwaddr.sa_data[4],
181  (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
182  return std::string(macstring);
183  }
184 
186  struct ifreq ifr;
187  /* I want to get an IPv4 IP address */
188  ifr.ifr_addr.sa_family = AF_INET;
189  /* I want IP address attached to "eth0" */
190  strncpy(ifr.ifr_name, _ifname.c_str(), IFNAMSIZ-1);
191  ioctl(_sockfd, SIOCGIFADDR, &ifr);
192  /* display result */
193  return std::string(inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
194  }
195 
197  struct ifaddrs *ifap, *ifa;
198  struct sockaddr_in *sa;
199  char *addr;
200  getifaddrs (&ifap);
201  for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
202  if ( strcmp(ifa->ifa_name,_ifname.c_str())==0 ){
203  if (ifa->ifa_addr->sa_family==AF_INET) {
204  sa = (struct sockaddr_in *) ifa->ifa_ifu.ifu_broadaddr;
205  addr = inet_ntoa(sa->sin_addr);
206  break;
207  }
208  }
209  }
210  freeifaddrs(ifap);
211  return std::string(addr);
212  }
213 
214  bool TransmitSocket::sendFrame(unsigned char * frame, const int & frameLen) {
215  _txMutex.lock();
216  _txBytes = send(_sockfd, frame, frameLen, 0);
217  _txMutex.unlock();
218  _sendCount ++;
219  _byteCount += _txBytes;
220  return (_txBytes>0);
221  }
222 
223  } /* namespace NDR651 */
224 }
bool sendFrame(unsigned char *frame, const int &frameLen)
Sends a frame of data.
std::string getIpBroadcastAddress()
Gets the IP broadcast address.
Defines functionality for LibCyberRadio applications.
Definition: App.h:23
std::string getMacAddress()
Gets the MAC address.
TransmitSocket(const std::string &ifname, unsigned int sport)
Constructs a TransmitSocket object.
std::string getIpAddress()
Gets the IP address.
virtual ~TransmitSocket()
Destroys a TransmitSocket object.