static int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int pf, int socktype, int dummy3) { const char *protname = argv[1]; char *garbage; union sockaddr_union us; socklen_t uslen = sizeof(us); int ipproto; bool needbind = false; int result; if (argc != 2) { Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); return STAT_NORETRY; } if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) { Error2("xioopen_rawip_recvfrom(\"%s\",,): protocol number exceeds 255 (%u)", protname, ipproto); return STAT_NORETRY; } else if (*garbage) { Warn1("xioopen_rawip_recvfrom(\"%s\",,): trailing garbage in protocol specification", protname); /*return STAT_NORETRY;*/ } xfd->stream.howtoshut = XIOSHUT_NONE; xfd->stream.howtoclose = XIOCLOSE_CLOSE; retropt_socket_pf(opts, &pf); if (pf == PF_UNSPEC) { #if WITH_IP4 && WITH_IP6 pf = xioopts.default_ip=='6'?PF_INET6:PF_INET; #elif WITH_IP6 pf = PF_INET6; #else pf = PF_INET; #endif } if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, 1, xfd->stream.para.socket.ip.res_opts[0], xfd->stream.para.socket.ip.res_opts[1]) != STAT_NOACTION) { needbind = true; } xfd->stream.dtype = XIODATA_RECVFROM_SKIPIP_ONE; if ((result = _xioopen_dgram_recvfrom(&xfd->stream, xioflags, needbind?&us.soa:NULL, uslen, opts, pf, socktype, ipproto, E_ERROR)) != STAT_OK) { return result; } _xio_openlate(&xfd->stream, opts); return STAT_OK; }
static int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) { /* we expect the form: filename */ const char *name; xiosingle_t *xfd = &xxfd->stream; int pf = PF_UNIX; int socktype = SOCK_DGRAM; int protocol = 0; struct sockaddr_un us; socklen_t uslen; bool tight = true; bool needbind = true; bool opt_unlink_early = false; bool opt_unlink_close = true; if (argc != 2) { Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); return STAT_NORETRY; } name = argv[1]; retropt_socket_pf(opts, &pf); retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight); uslen = xiosetunix(pf, &us, name, abstract, tight); xfd->howtoend = END_NONE; retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen, 1, 0, 0); if (!(ABSTRACT && abstract)) { /* only for non abstract because abstract do not work in file system */ retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); if (opt_unlink_close) { if ((xfd->unlink_close = strdup(name)) == NULL) { Error1("strdup(\"%s\"): out of memory", name); } xfd->opt_unlink_close = true; } if (opt_unlink_early) { if (Unlink(name) < 0) { if (errno == ENOENT) { Warn2("unlink(\"%s\"): %s", name, strerror(errno)); } else { Error2("unlink(\"%s\"): %s", name, strerror(errno)); } } } } xfd->para.socket.la.soa.sa_family = pf; xfd->dtype = XIODATA_RECVFROM_ONE; return _xioopen_dgram_recvfrom(xfd, xioflags, needbind?(struct sockaddr *)&us:NULL, uslen, opts, pf, socktype, protocol, E_ERROR); }
static int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int pf, int socktype, int ipproto) { union sockaddr_union us; socklen_t uslen = sizeof(us); bool needbind = false; int result; if (argc != 2) { Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); return STAT_NORETRY; } xfd->stream.howtoend = END_NONE; retropt_socket_pf(opts, &pf); if (pf == PF_UNSPEC) { #if WITH_IP4 && WITH_IP6 pf = xioopts.default_ip=='6'?PF_INET6:PF_INET; #elif WITH_IP6 pf = PF_INET6; #else pf = PF_INET; #endif } if ((result = xiogetaddrinfo(NULL, argv[1], pf, socktype, ipproto, &us, &uslen, xfd->stream.para.socket.ip.res_opts[0], xfd->stream.para.socket.ip.res_opts[1])) != STAT_OK) { return result; } if (pf == PF_UNSPEC) { pf = us.soa.sa_family; } { union sockaddr_union la; socklen_t lalen = sizeof(la); if (retropt_bind(opts, pf, socktype, ipproto, &la.soa, &lalen, 1, xfd->stream.para.socket.ip.res_opts[0], xfd->stream.para.socket.ip.res_opts[1]) != STAT_NOACTION) { switch (pf) { #if WITH_IP4 case PF_INET: us.ip4.sin_addr = la.ip4.sin_addr; break; #endif #if WITH_IP6 case PF_INET6: us.ip6.sin6_addr = la.ip6.sin6_addr; break; #endif } needbind = true; } } if (retropt_ushort(opts, OPT_SOURCEPORT, &xfd->stream.para.socket.ip.sourceport) >= 0) { xfd->stream.para.socket.ip.dosourceport = true; } retropt_bool(opts, OPT_LOWPORT, &xfd->stream.para.socket.ip.lowport); xfd->stream.dtype = XIODATA_RECVFROM_ONE; if ((result = _xioopen_dgram_recvfrom(&xfd->stream, xioflags, &us.soa, uslen, opts, pf, socktype, ipproto, E_ERROR)) != STAT_OK) { return result; } _xio_openlate(&xfd->stream, opts); return STAT_OK; }
static int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xxfd, unsigned groups, int abstract, int dummy2, int dummy3) { /* we expect the form: filename */ const char *name; xiosingle_t *xfd = &xxfd->stream; int pf = PF_UNIX; int socktype = SOCK_DGRAM; int protocol = 0; struct sockaddr_un us; socklen_t uslen; bool needbind = true; bool opt_unlink_early = false; bool opt_unlink_close = true; if (argc != 2) { Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1); return STAT_NORETRY; } name = argv[1]; xfd->para.socket.un.tight = true; retropt_socket_pf(opts, &pf); xfd->howtoend = END_NONE; if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY; applyopts(-1, opts, PH_INIT); applyopts_named(name, opts, PH_EARLY); /* umask! */ applyopts_offset(xfd, opts); if (!(ABSTRACT && abstract)) { /* only for non abstract because abstract do not work in file system */ retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); retropt_bool(opts, OPT_UNLINK_CLOSE, &opt_unlink_close); } applyopts(-1, opts, PH_EARLY); uslen = xiosetunix(pf, &us, name, abstract, xfd->para.socket.un.tight); #if 0 if (retropt_bind(opts, pf, socktype, protocol, (struct sockaddr *)&us, &uslen, (abstract<<1)|xfd->para.socket.un.tight, 0, 0) == STAT_OK) { } #endif if (!(ABSTRACT && abstract)) { if (opt_unlink_early) { if (Unlink(name) < 0) { if (errno == ENOENT) { Warn2("unlink(\"%s\"): %s", name, strerror(errno)); } else { Error2("unlink(\"%s\"): %s", name, strerror(errno)); } } } else { struct stat buf; if (Lstat(name, &buf) == 0) { Error1("\"%s\" exists", name); return STAT_RETRYLATER; } } if (opt_unlink_close) { if ((xfd->unlink_close = strdup(name)) == NULL) { Error1("strdup(\"%s\"): out of memory", name); } xfd->opt_unlink_close = true; } /* trying to set user-early, perm-early etc. here is useless because file system entry is available only past bind() call. */ } applyopts_named(name, opts, PH_EARLY); /* umask! */ xfd->para.socket.la.soa.sa_family = pf; xfd->dtype = XIODATA_RECVFROM_ONE; /* this may fork */ return _xioopen_dgram_recvfrom(xfd, xioflags, needbind?(struct sockaddr *)&us:NULL, uslen, opts, pf, socktype, protocol, E_ERROR); }