int handle() { nlSystemUseChangeLock.startReadAccess(); int ret = -1; if(bNetworkInited) { // only do that if we have the network system still up // this should already close the socket but not lock other parts in HawkNL nlPrepareClose(sock); // hopefully this does not block anymore ret = (nlClose(sock) != NL_FALSE) ? 0 : -1; } nlSystemUseChangeLock.endReadAccess(); return ret; }
int main(int argc, char **argv) { NLboolean isserver = NL_FALSE; NLsocket serversock; NLsocket clientsock; NLaddress addr; NLbyte server[] = "127.0.0.1:25000"; NLenum type = NL_UNRELIABLE; /* Change this to NL_RELIABLE for reliable connection */ NLbyte string[NL_MAX_STRING_LENGTH]; if(!nlInit()) printErrorExit(); printf("nlGetString(NL_VERSION) = %s\n\n", nlGetString(NL_VERSION)); printf("nlGetString(NL_NETWORK_TYPES) = %s\n\n", nlGetString(NL_NETWORK_TYPES)); if(!nlSelectNetwork(NL_IP)) printErrorExit(); if(argc > 1) { if(!strcmp(argv[1], "-s")) /* server mode */ isserver = NL_TRUE; } if(isserver) { /* create a server socket */ serversock = nlOpen(25000, type); /* just a random port number ;) */ if(serversock == NL_INVALID) printErrorExit(); if(!nlListen(serversock)) /* let's listen on this socket */ { nlClose(serversock); printErrorExit(); } nlGetLocalAddr(serversock, &addr); printf("Server address is %s\n", nlAddrToString(&addr, string)); mainServerLoop(serversock); } else { /* create a client socket */ clientsock = nlOpen(0, type); /* let the system assign the port number */ nlGetLocalAddr(clientsock, &addr); printf("our address is %s\n", nlAddrToString(&addr, string)); if(clientsock == NL_INVALID) printErrorExit(); /* create the NLaddress */ nlStringToAddr(server, &addr); printf("Address is %s\n", nlAddrToString(&addr, string)); /* now connect */ if(!nlConnect(clientsock, &addr)) { nlClose(clientsock); printErrorExit(); } mainClientLoop(clientsock); } nlShutdown(); return 0; }
/** * nlComm: * @nlmsg: pointer to netlink message * @respbuf: pointer to pointer where response buffer will be allocated * @respbuflen: pointer to integer holding the size of the response buffer * on return of the function. * @nl_pid: the pid of the process to talk to, i.e., pid = 0 for kernel * * Send the given message to the netlink layer and receive response. * Returns 0 on success, -1 on error. In case of error, no response * buffer will be returned. */ static int nlComm(struct nlmsghdr *nlmsg, char **respbuf, unsigned int *respbuflen, int nl_pid) { int rc = 0; struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK, .nl_pid = nl_pid, .nl_groups = 0, }; int rcvChunkSize = 1024; // expecting less than that int rcvoffset = 0; ssize_t nbytes; struct timeval tv = { .tv_sec = NETLINK_ACK_TIMEOUT_S, }; fd_set readfds; int fd = nlOpen(); int n; if (fd < 0) return -1; nlmsg->nlmsg_pid = getpid(); nlmsg->nlmsg_flags |= NLM_F_ACK; nbytes = sendto(fd, (void *)nlmsg, nlmsg->nlmsg_len, 0, (struct sockaddr *)&nladdr, sizeof(nladdr)); if (nbytes < 0) { virReportSystemError(errno, "%s", _("cannot send to netlink socket")); rc = -1; goto err_exit; } FD_ZERO(&readfds); FD_SET(fd, &readfds); n = select(fd + 1, &readfds, NULL, NULL, &tv); if (n <= 0) { if (n < 0) virReportSystemError(errno, "%s", _("error in select call")); if (n == 0) virReportSystemError(ETIMEDOUT, "%s", _("no valid netlink response was received")); rc = -1; goto err_exit; } while (1) { if (VIR_REALLOC_N(*respbuf, rcvoffset+rcvChunkSize) < 0) { virReportOOMError(); rc = -1; goto err_exit; } socklen_t addrlen = sizeof(nladdr); nbytes = recvfrom(fd, &((*respbuf)[rcvoffset]), rcvChunkSize, 0, (struct sockaddr *)&nladdr, &addrlen); if (nbytes < 0) { if (errno == EAGAIN || errno == EINTR) continue; virReportSystemError(errno, "%s", _("error receiving from netlink socket")); rc = -1; goto err_exit; } rcvoffset += nbytes; break; } *respbuflen = rcvoffset; err_exit: if (rc == -1) { VIR_FREE(*respbuf); *respbuf = NULL; *respbuflen = 0; } nlClose(fd); return rc; } static struct rtattr * rtattrCreate(char *buffer, int bufsize, int type, const void *data, int datalen) { struct rtattr *r = (struct rtattr *)buffer; r->rta_type = type; r->rta_len = RTA_LENGTH(datalen); if (r->rta_len > bufsize) return NULL; memcpy(RTA_DATA(r), data, datalen); return r; } static void nlInit(struct nlmsghdr *nlm, int flags, int type) { nlm->nlmsg_len = NLMSG_LENGTH(0); nlm->nlmsg_flags = flags; nlm->nlmsg_type = type; }