int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) { union sockaddr_union src = { .in6.sin6_family = AF_INET6, .in6.sin6_port = htobe16(DHCP6_PORT_CLIENT), .in6.sin6_scope_id = index, }; _cleanup_close_ int s = -1; int r; assert(index > 0); assert(local_address); src.in6.sin6_addr = *local_address; s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_UDP); if (s < 0) return -errno; r = setsockopt_int(s, IPPROTO_IPV6, IPV6_V6ONLY, true); if (r < 0) return r; r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, false); if (r < 0) return r; r = setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, true); if (r < 0) return r; r = bind(s, &src.sa, sizeof(src.in6)); if (r < 0) return -errno; return TAKE_FD(s); } int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, const void *packet, size_t len) { union sockaddr_union dest = { .in6.sin6_family = AF_INET6, .in6.sin6_port = htobe16(DHCP6_PORT_SERVER), }; int r; assert(server_address); memcpy(&dest.in6.sin6_addr, server_address, sizeof(dest.in6.sin6_addr)); r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in6)); if (r < 0) return -errno; return 0; }
int server_open_native_socket(Server *s) { static const union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/journal/socket", }; int r; assert(s); if (s->native_fd < 0) { s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (s->native_fd < 0) return log_error_errno(errno, "socket() failed: %m"); (void) sockaddr_un_unlink(&sa.un); r = bind(s->native_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)); if (r < 0) return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path); (void) chmod(sa.un.sun_path, 0666); } else (void) fd_nonblock(s->native_fd, true); r = setsockopt_int(s->native_fd, SOL_SOCKET, SO_PASSCRED, true); if (r < 0) return log_error_errno(r, "SO_PASSCRED failed: %m"); #if HAVE_SELINUX if (mac_selinux_use()) { r = setsockopt_int(s->native_fd, SOL_SOCKET, SO_PASSSEC, true); if (r < 0) log_warning_errno(r, "SO_PASSSEC failed: %m"); } #endif r = setsockopt_int(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, true); if (r < 0) return log_error_errno(r, "SO_TIMESTAMP failed: %m"); r = sd_event_add_io(s->event, &s->native_event_source, s->native_fd, EPOLLIN, server_process_datagram, s); if (r < 0) return log_error_errno(r, "Failed to add native server fd to event loop: %m"); r = sd_event_source_set_priority(s->native_event_source, SD_EVENT_PRIORITY_NORMAL+5); if (r < 0) return log_error_errno(r, "Failed to adjust native event source priority: %m"); return 0; }
static int setsockopt_keepalive(int sock) { if (setsockopt_int(sock, SOL_SOCKET, SO_KEEPALIVE, 1) < 0) { return -1; } if (setsockopt_int(sock, IPPROTO_TCP, TCP_KEEPIDLE, KEEPALIVE_IDLE)) { return -1; } if (setsockopt_int(sock, IPPROTO_TCP, TCP_KEEPINTVL, KEEPALIVE_INTVL)) { return -1; } if (setsockopt_int(sock, IPPROTO_TCP, TCP_KEEPCNT, KEEPALIVE_CNT)) { return -1; } return 0; }
/** * Mark address behind socket S as reusable. */ static inline int setsock_reuseaddr(int s) { #if defined SO_REUSEADDR return setsockopt_int(s, SOL_SOCKET, SO_REUSEADDR, 1); #else /* !SO_REUSEADDR */ return 0; #endif /* SO_REUSEADDR */ }
int tcp_srv_init(tcp_srv_t *srv, int port, tcp_func_t func, void *user_data) { struct sockaddr_in ilocal; tcp_srv_clear(srv); /* Create network socket */ if ((srv->csock.chan.fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { log_str("ERROR: socket(PF_INET, SOCK_STREAM): %s", strerror(errno)); return -1; } setsockopt_int(srv->csock.chan.fd, SOL_SOCKET, SO_REUSEADDR, 1); /* Bind network socket */ ilocal.sin_family = AF_INET; ilocal.sin_addr.s_addr = htonl(INADDR_ANY); ilocal.sin_port = htons(port); if (bind(srv->csock.chan.fd, (struct sockaddr *) &ilocal, sizeof(ilocal)) == -1) { log_str("ERROR: bind(%d): %s", port, strerror(errno)); close(srv->csock.chan.fd); srv->csock.chan.fd = -1; return -1; } /* Listen to network connection (with backlog of maximum 1 pending connection) */ if (listen(srv->csock.chan.fd, 1) == -1) { log_str("ERROR: listen: %s", strerror(errno)); close(srv->csock.chan.fd); srv->csock.chan.fd = -1; return -1; } log_str("Listening to TCP connections from port %d", port); /* Prevent child processes from inheriting this socket */ fcntl(srv->csock.chan.fd, F_SETFD, FD_CLOEXEC); srv->csock.chan.tag = sys_io_watch(srv->csock.chan.fd, (sys_io_func_t) tcp_srv_csock_event, srv); srv->func = func; srv->user_data = user_data; return 0; }
static void ping6(len_and_sockaddr *lsa) { struct icmp6_hdr *pkt; int c; int sockopt; pkt = (struct icmp6_hdr *) G.packet; /*memset(pkt, 0, sizeof(G.packet)); already is */ pkt->icmp6_type = ICMP6_ECHO_REQUEST; pkt->icmp6_id = G.myid; sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt); xsendto(pingsock, G.packet, DEFDATALEN + sizeof(struct icmp6_hdr), &lsa->u.sa, lsa->len); /* listen for replies */ while (1) { #if 0 struct sockaddr_in6 from; socklen_t fromlen = sizeof(from); c = recvfrom(pingsock, G.packet, sizeof(G.packet), 0, (struct sockaddr *) &from, &fromlen); #else c = recv(pingsock, G.packet, sizeof(G.packet), 0); #endif if (c < 0) { if (errno != EINTR) bb_perror_msg("recvfrom"); continue; } if (c >= ICMP_MINLEN) { /* icmp6_hdr */ if (pkt->icmp6_id != G.myid) continue; /* not our ping */ if (pkt->icmp6_type == ICMP6_ECHO_REPLY) break; } } if (ENABLE_FEATURE_CLEAN_UP) close(pingsock); }
int FAST_FUNC setsockopt_SOL_SOCKET_int(int fd, int optname, int optval) { return setsockopt_int(fd, SOL_SOCKET, optname, optval); }
int FAST_FUNC setsockopt_1(int fd, int level, int optname) { return setsockopt_int(fd, level, optname, 1); }
static void send_probe(int seq, int ttl) { int len, res; void *out; /* Payload */ #if ENABLE_TRACEROUTE6 if (dest_lsa->u.sa.sa_family == AF_INET6) { struct outdata6_t *pkt = (struct outdata6_t *) outip; pkt->ident6 = htonl(ident); pkt->seq6 = htonl(seq); /*gettimeofday(&pkt->tv, &tz);*/ } else #endif { outdata->seq = seq; outdata->ttl = ttl; // UNUSED: was storing gettimeofday's result there, but never ever checked it /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/ if (option_mask32 & OPT_USE_ICMP) { outicmp->icmp_seq = htons(seq); /* Always calculate checksum for icmp packets */ outicmp->icmp_cksum = 0; outicmp->icmp_cksum = inet_cksum((uint16_t *)outicmp, packlen - (sizeof(*outip) + optlen)); if (outicmp->icmp_cksum == 0) outicmp->icmp_cksum = 0xffff; } } //BUG! verbose is (x & OPT_VERBOSE), not a counter! #if 0 //ENABLE_FEATURE_TRACEROUTE_VERBOSE /* XXX undocumented debugging hack */ if (verbose > 1) { const uint16_t *sp; int nshorts, i; sp = (uint16_t *)outip; nshorts = (unsigned)packlen / sizeof(uint16_t); i = 0; printf("[ %d bytes", packlen); while (--nshorts >= 0) { if ((i++ % 8) == 0) printf("\n\t"); printf(" %04x", ntohs(*sp)); sp++; } if (packlen & 1) { if ((i % 8) == 0) printf("\n\t"); printf(" %02x", *(unsigned char *)sp); } printf("]\n"); } #endif #if ENABLE_TRACEROUTE6 if (dest_lsa->u.sa.sa_family == AF_INET6) { res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl); if (res != 0) bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl); out = outip; len = packlen; } else #endif { #if defined IP_TTL res = setsockopt_int(sndsock, IPPROTO_IP, IP_TTL, ttl); if (res != 0) bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl); #endif out = outicmp; len = packlen - sizeof(*outip); if (!(option_mask32 & OPT_USE_ICMP)) { out = outdata; len -= sizeof(*outudp); set_nport(&dest_lsa->u.sa, htons(port + seq)); } } res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len); if (res != len) bb_info_msg("sent %d octets, ret=%d", len, res); }