PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/modules/corenova/net/socket.c

https://github.com/saintkepha/corenova
C | 373 lines | 297 code | 68 blank | 8 comment | 48 complexity | 6b0dbebf9345b6b3a9b245bdf3eb09f8 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0
  1. #include <corenova/source-stub.h>
  2. THIS = {
  3. .version = "2.1",
  4. .author = "Peter K. Lee <saint@corenova.com>",
  5. .description = "This module provides low level socket support.",
  6. .requires = LIST("corenova.data.list",
  7. "corenova.net.resolve"),
  8. .implements = LIST("Socket", "SocketPair")
  9. };
  10. #include <corenova/net/socket.h>
  11. #include <corenova/net/resolve.h>
  12. #include <corenova/data/list.h>
  13. /*//////// MODULE CODE //////////////////////////////////////////*/
  14. #include <errno.h>
  15. #include <unistd.h>
  16. #include <sys/ioctl.h>
  17. #include <netinet/in.h> /* for htons() */
  18. #if defined (linux)
  19. #include <net/if_arp.h>
  20. #include <linux/if.h>
  21. #include <linux/if_packet.h>
  22. #include <linux/netlink.h>
  23. #include <linux/if_ether.h>
  24. #else
  25. #include <sys/socket.h>
  26. #include <net/if.h>
  27. #include <net/if_arp.h>
  28. #define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */
  29. struct sockaddr_ll {
  30. uint16_t sll_family;
  31. uint16_t sll_protocol;
  32. int32_t sll_ifindex;
  33. uint16_t sll_hatype;
  34. unsigned char sll_pkttype;
  35. unsigned char sll_halen;
  36. unsigned char sll_addr[8];
  37. };
  38. #endif
  39. #if defined(freebsd8)
  40. #include <net/if.h>
  41. #include <net/if_dl.h>
  42. #endif
  43. #if defined (solaris2)
  44. #include <sys/sockio.h>
  45. #endif
  46. /*//////// API ROUTINES //////////////////////////////////////////*/
  47. static socket_t *
  48. _new(enum _socketTypes type) {
  49. socket_t *sock = (socket_t *) calloc(1, sizeof (socket_t));
  50. if (sock) {
  51. DEBUGP(DDEBUG, "new", "accessing socket type [%s]", _socketDescr[type]);
  52. sock->type = type;
  53. switch (type) {
  54. case SOCKET_DGRAM:
  55. sock->skd = socket(AF_INET, SOCK_DGRAM, 0);
  56. break;
  57. #if defined (linux)
  58. case SOCKET_NETLINK:
  59. sock->skd = socket(AF_NETLINK, SOCK_RAW, NETLINK_USERSOCK);
  60. break;
  61. case SOCKET_RAW:
  62. sock->skd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
  63. break;
  64. #endif
  65. case SOCKET_STREAM:
  66. sock->skd = socket(AF_INET, SOCK_STREAM, 0);
  67. break;
  68. case SOCKET_DUMMY:
  69. break;
  70. case SOCKET_UNIX:
  71. sock->skd = socket(AF_UNIX, SOCK_STREAM, 0);
  72. break;
  73. default:
  74. sock->skd = -1;
  75. break;
  76. }
  77. if (sock->skd == -1) {
  78. DEBUGP(DERR, "create", "unable to create socket type [%d]", type);
  79. free(sock);
  80. sock = NULL;
  81. }
  82. }
  83. return sock;
  84. }
  85. static void
  86. _destroy(socket_t **sock) {
  87. if (sock && *sock) {
  88. if ((*sock)->skd > 0)
  89. close((*sock)->skd);
  90. free(*sock);
  91. *sock = NULL;
  92. }
  93. }
  94. static boolean_t
  95. _bindInterface(socket_t *sock, const char *ifname) { // freebsd8 code is not correct here
  96. if (sock && ifname) {
  97. struct ifreq req;
  98. #if !defined(freebsd8)
  99. struct sockaddr_ll skaddr;
  100. #else
  101. struct sockaddr_dl skaddr;
  102. #endif
  103. // set the interface
  104. memset(&req, 0, sizeof (struct ifreq));
  105. strncpy(req.ifr_name, ifname, IFNAMSIZ);
  106. req.ifr_name[IFNAMSIZ - 1] = '\0';
  107. // verify that the interface exists
  108. if (ioctl(sock->skd, SIOCGIFINDEX, &req) >= 0) {
  109. // bind to the interface
  110. memset(&skaddr, 0, sizeof (skaddr));
  111. #if defined (linux)
  112. skaddr.sll_protocol = htons(ETH_P_ALL);
  113. skaddr.sll_ifindex = req.ifr_ifindex;
  114. skaddr.sll_family = AF_PACKET;
  115. #elif defined(freebsd8)
  116. skaddr.sdl_index = req.ifr_index;
  117. skaddr.sdl_family = AF_LINK;
  118. #else
  119. skaddr.sll_family = AF_ROUTE;
  120. #endif
  121. #if !defined(freebsd8)
  122. if (bind(sock->skd, (struct sockaddr *) &skaddr, sizeof (struct sockaddr_ll)) >= 0)
  123. #else
  124. if (bind(sock->skd, (struct sockaddr *) &req.ifr_addr, sizeof (struct sockaddr)) >= 0)
  125. #endif
  126. return TRUE;
  127. else {
  128. DEBUGP(DERR, "bindInterface", "unable to bind socket to %s:%s", ifname, strerror(errno));
  129. }
  130. } else {
  131. DEBUGP(DERR, "bindInterface", "interface %s does not exist.", ifname);
  132. }
  133. }
  134. return FALSE;
  135. }
  136. static boolean_t
  137. _bind(socket_t *sock, struct sockaddr* addr) {
  138. if (sock && addr) {
  139. if (bind(sock->skd, (struct sockaddr *) addr, sizeof (struct sockaddr)) >= 0) {
  140. return TRUE;
  141. }
  142. else {
  143. DEBUGP(DERR, "bind", "unable to bind socket: %s", strerror(errno));
  144. }
  145. }
  146. return FALSE;
  147. }
  148. static boolean_t
  149. _setOpt(socket_t *sock, int opt) {
  150. int32_t val = 0;
  151. int res = 0;
  152. if (sock) {
  153. switch (opt) {
  154. case BCAST:
  155. DEBUGP(DDEBUG, "setOpt", "enabling BROADCAST on socket #%u", sock->skd);
  156. val = 1;
  157. res = setsockopt(sock->skd, SOL_SOCKET, SO_BROADCAST, &val, sizeof (val));
  158. break;
  159. }
  160. if (res == 0) return TRUE;
  161. DEBUGP(DWARN, "setOpt", "setsockopt() failed: %s", strerror(errno));
  162. }
  163. return FALSE;
  164. }
  165. static boolean_t
  166. _setFlag(socket_t *sock, const char *ifname, short flag) {
  167. if (sock) {
  168. struct ifreq ifr;
  169. strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
  170. ifr.ifr_name[IFNAMSIZ - 1] = '\0';
  171. if (ioctl(sock->skd, SIOCGIFFLAGS, &ifr) >= 0) {
  172. ifr.ifr_flags |= flag;
  173. if (ioctl(sock->skd, SIOCSIFFLAGS, &ifr) >= 0)
  174. return TRUE;
  175. }
  176. }
  177. return FALSE;
  178. }
  179. static boolean_t
  180. _clearFlag(socket_t *sock, const char *ifname, short flag) {
  181. if (sock) {
  182. struct ifreq ifr;
  183. strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
  184. ifr.ifr_name[IFNAMSIZ - 1] = '\0';
  185. if (ioctl(sock->skd, SIOCGIFFLAGS, &ifr) >= 0) {
  186. ifr.ifr_flags &= ~flag;
  187. if (ioctl(sock->skd, SIOCSIFFLAGS, &ifr) >= 0)
  188. return TRUE;
  189. }
  190. }
  191. return FALSE;
  192. }
  193. static boolean_t
  194. _verifyArpType(socket_t *sock, const char *ifname, u_int16_t type) {
  195. if (sock) {
  196. struct ifreq ifr;
  197. strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
  198. ifr.ifr_name[IFNAMSIZ - 1] = '\0';
  199. #if defined (linux)
  200. if (ioctl(sock->skd, SIOCGIFHWADDR, &ifr) >= 0) {
  201. if (ifr.ifr_hwaddr.sa_family == type)
  202. return TRUE;
  203. }
  204. #elif defined (freebsd6) || defined (freebsd7)
  205. if (ioctl(sock->skd, SIOCGIFADDR, &ifr) >= 0) {
  206. if (ifr.ifr_ifru.ifru_phys == type)
  207. return TRUE;
  208. }
  209. #else
  210. if (ioctl(sock->skd, SIOCGIFADDR, &ifr) >= 0) {
  211. // XXX - hack for now!!!
  212. return TRUE;
  213. }
  214. #endif
  215. DEBUGP(DERR, "verifyArpType", "%s", strerror(errno));
  216. }
  217. return FALSE;
  218. }
  219. static boolean_t
  220. setAddressSocket(socket_t *socket, const char *to, int port) {
  221. if (socket && to) {
  222. switch (socket->type) {
  223. case SOCKET_DGRAM:
  224. case SOCKET_STREAM:
  225. {
  226. in_addr_t ip = I(Resolve)->name2ip(to);
  227. if (ip != INADDR_NONE) {
  228. socket->addr.in.sin_family = AF_INET;
  229. socket->addr.in.sin_addr.s_addr = ip;
  230. socket->addr.in.sin_port = htons(port);
  231. socket->len = sizeof (socket->addr.in);
  232. return TRUE;
  233. } else {
  234. DEBUGP(DERR, "setAddress", "unable to resolve %s for setting socket address!", to);
  235. }
  236. break;
  237. }
  238. case SOCKET_UNIX:
  239. {
  240. memset((char *) &socket->addr.un, 0, sizeof (socket->addr.un));
  241. socket->addr.un.sun_family = AF_UNIX;
  242. strncpy(socket->addr.un.sun_path, to, sizeof (socket->addr.un));
  243. socket->len = sizeof (socket->addr.un);
  244. return TRUE;
  245. }
  246. case SOCKET_DUMMY:
  247. case SOCKET_NETLINK:
  248. case SOCKET_RAW:
  249. default:
  250. DEBUGP(DWARN, "setAddress", "cannot set address for '%s' socket!", _socketDescr[socket->type]);
  251. }
  252. }
  253. return FALSE;
  254. }
  255. IMPLEMENT_INTERFACE(Socket) = {
  256. .new = _new,
  257. .destroy = _destroy,
  258. .bindInterface = _bindInterface,
  259. .setFlag = _setFlag,
  260. .clearFlag = _clearFlag,
  261. .verifyArpType = _verifyArpType,
  262. .setOpt = _setOpt,
  263. .setAddress = setAddressSocket,
  264. .bind = _bind
  265. };
  266. /*//////// SocketPair Interface Implementation //////////////////////////////////////////*/
  267. static socket_pair_t *
  268. newSocketPair(void) {
  269. socket_pair_t *pair = (socket_pair_t *) calloc(1, sizeof (socket_pair_t));
  270. if (pair) {
  271. if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair->fds) < 0) {
  272. DEBUGP(DERR, "newSocketPair", "failed to create a new socket pair!");
  273. free(pair);
  274. pair = NULL;
  275. }
  276. }
  277. return pair;
  278. }
  279. static void
  280. closeSocketPair(socket_pair_t *pair) {
  281. if (pair) {
  282. /* do a soft close until it is explicitly destroyed! */
  283. DEBUGP(DDEBUG, "closeSocketPair", "a soft close of %d and %d", pair->fds[0], pair->fds[1]);
  284. shutdown(pair->fds[0], SHUT_RDWR);
  285. shutdown(pair->fds[1], SHUT_RDWR);
  286. }
  287. }
  288. static void
  289. destroySocketPair(socket_pair_t **ptr) {
  290. if (ptr) {
  291. socket_pair_t *pair = *ptr;
  292. if (pair) {
  293. DEBUGP(DDEBUG, "destroySocketPair", "a full close of %d and %d", pair->fds[0], pair->fds[1]);
  294. close(pair->fds[0]);
  295. close(pair->fds[1]);
  296. free(pair);
  297. *ptr = NULL;
  298. }
  299. }
  300. }
  301. IMPLEMENT_INTERFACE(SocketPair) = {
  302. .new = newSocketPair,
  303. .close = closeSocketPair,
  304. .destroy = destroySocketPair
  305. };