static int lua_cwd(lua_State *L) { #ifdef _WIN32 char drv[2]; int l; SB sb; sbinit(&sb); drv[0] = '.'; drv[1] = 0; l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0); if (l > sb.maxlen) { sbgrow(&sb, l+1); l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0); } if (l <= 0) return sbsetpush(L, &sb, "."); sb.len += l; return sbpush(L, &sb); #elif HAVE_GETCWD const char *s; SB sb; sbinit(&sb); s = getcwd(sb.buffer, sb.maxlen); while (!s && errno==ERANGE) { sbgrow(&sb, sb.maxlen + SBINCREMENT); s = getcwd(sb.buffer, sb.maxlen); } if (! s) return sbsetpush(L, &sb, "."); sb.len += strlen(s); return sbpush(L, &sb); #else const char *s; SB sb; sbinit(&sb); sbgrow(&sb, PATH_MAX); s = getwd(sb.buffer); if (! s) return sbsetpush(L, &sb, "."); sb.len += strlen(s); return sbpush(L, &sb); #endif }
static const char * executable_dir(const char *progname) { SB sb; struct stat sbuf; if (! progname) return 0; sbinit(&sb); if (progname[0]=='/') sbaddn(&sb, progname, strlen(progname)); else if (strchr(progname,'/')) sbaddsf(&sb,catpath(NULL,progname)); else { char *p = getenv("PATH"); for (;;) { sb.len = 0; if (! (p && *p)) return sbfree(&sb); while (*p && *p!=':') sbadd1(&sb, *p++); if (*p ==':') p++; sbadd1(&sb, 0); sb.len = 0; sbaddsf(&sb, catpath(sb.buffer, progname)); sbadd1(&sb, 0); if (sb.buffer && stat(sb.buffer,&sbuf)>=0 && S_ISREG(sbuf.st_mode)) if (access(sb.buffer, X_OK) >= 0) break; } } #ifdef S_ISLNK sbadd1(&sb, 0); while(sb.buffer && lstat(sb.buffer,&sbuf)>=0 && S_ISLNK(sbuf.st_mode)) { int h,l; sbaddn(&sb,"../",3); h = sb.len; while ((l=readlink(sb.buffer,sb.buffer+h,sb.maxlen-h))>=sb.maxlen-h) sbgrow(&sb, sb.maxlen - h + SBINCREMENT); if (l < 0) return sbfree(&sb); sb.len = h + l; sbadd1(&sb,0); sb.len = 0; sbaddsf(&sb, catpath(sb.buffer,sb.buffer+h-3)); sbadd1(&sb,0); } #endif while (sb.buffer && sb.len>0 && sb.buffer[sb.len-1]=='/') sb.len -= 1; while (sb.buffer && sb.len>0 && sb.buffer[sb.len-1]!='/') sb.len -= 1; while (sb.buffer && sb.len>0 && sb.buffer[sb.len-1]=='/') sb.len -= 1; sbadd1(&sb, 0); return sb.buffer; }
static char * catpath(const char *from, const char *fname) { SB sb; sbinit(&sb); if (fname && fname[0]=='/') sbadd1(&sb, '/'); else if (from) sbaddsf(&sb, catpath(NULL,from)); else { char *cwd = 0; while (sb.buffer && !cwd) { cwd = getcwd(sb.buffer + sb.len, sb.maxlen - sb.len); if (cwd || errno != ERANGE) break; sbgrow(&sb, sb.maxlen - sb.len + SBINCREMENT); } if (cwd) sb.len += strlen(cwd); else sbfree(&sb); } for (;;) { while (fname && fname[0]=='/') fname++; if (!fname || !fname[0]) { while (&sb.buffer && sb.len>0 && sb.buffer[sb.len-1]=='/') sb.len -= 1; sbadd1(&sb, 0); return sb.buffer; } if (fname[0]=='.') { if (fname[1]=='/' || fname[1]==0) { fname +=1; continue; } if (fname[1]=='.') if (fname[2]=='/' || fname[2]==0) { fname +=2; while (sb.buffer && sb.len>0 && sb.buffer[sb.len-1]=='/') sb.len -= 1; while (sb.buffer && sb.len>0 && sb.buffer[sb.len-1]!='/') sb.len -= 1; continue; } } if (sb.len==0 || (sb.buffer && sb.buffer[sb.len-1]!='/')) sbadd1(&sb, '/'); while (*fname!=0 && *fname!='/') sbadd1(&sb, *fname++); } sbadd1(&sb, 0); return sb.buffer; }
static char *concatargs(int cargc, char **cargv) { static char bigbuf[1024]; StringBuf b; int i; sbinit(&b, bigbuf, sizeof(bigbuf)); for(i=0;i<cargc;i++) { sbaddstr(&b, cargv[i]); sbaddchar(&b, ' '); } sbterminate(&b); return bigbuf; }
int ncp_sock_recv(struct socket *so, struct sockbuf *sio) { int error, flags; sbinit(sio, 1000000); /* limit data returned (inexact, hint only) */ flags = MSG_DONTWAIT; error = so_pru_soreceive(so, NULL, NULL, sio, NULL, &flags); #ifdef NCP_SOCKET_DEBUG if (error) kprintf("ncp_recv: err=%d\n", error); #endif return (error); }
static int dbapi2_adapter_quotestring(const DBAPIConn *db, char *buf, size_t buflen, const char *data, size_t len) { StringBuf b; sbinit(&b, buf, buflen); char xbuf[len * 2 + 5]; size_t esclen; esclen = dbescapestring(xbuf, (char *)data, len); sbaddchar(&b, '\''); sbaddstrlen(&b, xbuf, esclen); sbaddchar(&b, '\''); if(!sbterminate(&b)) return 0; return 1; }
static const char * relocate_path(const char *dir, const char *s) { SB sb; const char *r; const char *execdir = LUA_EXECDIR; int lexecdir = strlen(execdir); int ldir = strlen(dir); sbinit(&sb); while ((r = strstr(s, execdir))) { sbaddn(&sb, s, r-s); sbaddn(&sb, dir, ldir); s = r + lexecdir; while (is_slash(s[0])) { if (is_dot(s[1]) && is_slash(s[2])) { s += 2; continue; } if (is_dot(s[1]) && is_dot(s[2]) && is_slash(s[3]) ) { s += 3; while (sb.buffer && sb.len>0 && is_slash(sb.buffer[sb.len-1])) sb.len -= 1; while (sb.buffer && sb.len>0 && !is_slash(sb.buffer[sb.len-1])) sb.len -= 1; while (sb.buffer && sb.len>0 && is_slash(sb.buffer[sb.len-1])) sb.len -= 1; continue; } break; } } sbaddn(&sb, s, strlen(s)); sbadd1(&sb, 0); #ifdef LUA_WIN r = _strdup(sb.buffer); #else r = strdup(sb.buffer); #endif sbfree(&sb); return r; }
/* | so_recv gets called when there is at least | an iSCSI header in the queue */ static int so_recv(isc_session_t *sp, pduq_t *pq) { struct socket *so = sp->soc; sn_t *sn = &sp->sn; struct uio *uio = &pq->uio; struct sockbuf sbp; pdu_t *pp; int error; size_t n, len; bhs_t *bhs; u_int max, exp; debug_called(8); /* | now calculate how much data should be in the buffer | NOTE: digest is not verified/calculated - yet */ pp = &pq->pdu; bhs = &pp->ipdu.bhs; sbinit(&sbp, 0); len = 0; if(bhs->AHSLength) { pp->ahs_len = bhs->AHSLength * 4; len += pp->ahs_len; } if(sp->hdrDigest) len += 4; if(bhs->DSLength) { n = bhs->DSLength; #if BYTE_ORDER == LITTLE_ENDIAN pp->ds_len = ((n & 0x00ff0000) >> 16) | (n & 0x0000ff00) | ((n & 0x000000ff) << 16); #else pp->ds_len = n; #endif len += pp->ds_len; while(len & 03) len++; if(sp->dataDigest) len += 4; }
static void ncp_watchdog(struct ncp_conn *conn) { char *buf; int error, len, flags; struct socket *so; struct sockaddr *sa; struct sockbuf sio; sa = NULL; while (conn->wdg_so) { /* not a loop */ so = conn->wdg_so; sbinit(&sio, 1000000); flags = MSG_DONTWAIT; error = so_pru_soreceive(so, (struct sockaddr**)&sa, NULL, &sio, NULL, &flags); if (error) break; len = sio.sb_cc; NCPSDEBUG("got watch dog %d\n",len); if (len != 2) { m_freem(sio.sb_mb); break; } buf = mtod(sio.sb_mb, char *); if (buf[1] != '?') { m_freem(sio.sb_mb); break; } buf[1] = 'Y'; error = so_pru_sosend(so, sa, NULL, sio.sb_mb, NULL, 0, curthread); NCPSDEBUG("send watch dog %d\n",error); break; } if (sa) kfree(sa, M_SONAME); return; }
/* * portal_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred, * struct file *a_fp) */ static int portal_open(struct vop_open_args *ap) { struct socket *so = 0; struct portalnode *pt; struct thread *td = curthread; struct vnode *vp = ap->a_vp; struct uio auio; struct iovec aiov[2]; struct sockbuf sio; int res; struct mbuf *cm = 0; struct cmsghdr *cmsg; int newfds; int *ip; int fd; int error; int len; struct portalmount *fmp; struct file *fp; struct portal_cred pcred; /* * Nothing to do when opening the root node. */ if (vp->v_flag & VROOT) return (vop_stdopen(ap)); /* * Can't be opened unless the caller is set up * to deal with the side effects. Check for this * by testing whether the p_dupfd has been set. */ KKASSERT(td->td_proc); if (td->td_lwp->lwp_dupfd >= 0) return (ENODEV); pt = VTOPORTAL(vp); fmp = VFSTOPORTAL(vp->v_mount); /* * Create a new socket. */ error = socreate(AF_UNIX, &so, SOCK_STREAM, 0, td); if (error) goto bad; /* * Reserve some buffer space */ res = pt->pt_size + sizeof(pcred) + 512; /* XXX */ error = soreserve(so, res, res, &td->td_proc->p_rlimit[RLIMIT_SBSIZE]); if (error) goto bad; /* * Kick off connection */ error = portal_connect(so, (struct socket *)fmp->pm_server->f_data); if (error) goto bad; /* * Wait for connection to complete */ /* * XXX: Since the mount point is holding a reference on the * underlying server socket, it is not easy to find out whether * the server process is still running. To handle this problem * we loop waiting for the new socket to be connected (something * which will only happen if the server is still running) or for * the reference count on the server socket to drop to 1, which * will happen if the server dies. Sleep for 5 second intervals * and keep polling the reference count. XXX. */ crit_enter(); while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { if (fmp->pm_server->f_count == 1) { error = ECONNREFUSED; crit_exit(); goto bad; } (void) tsleep((caddr_t) &so->so_timeo, 0, "portalcon", 5 * hz); } crit_exit(); if (so->so_error) { error = so->so_error; goto bad; } /* * Set miscellaneous flags */ so->so_rcv.ssb_timeo = 0; so->so_snd.ssb_timeo = 0; atomic_set_int(&so->so_rcv.ssb_flags, SSB_NOINTR); atomic_set_int(&so->so_snd.ssb_flags, SSB_NOINTR); pcred.pcr_flag = ap->a_mode; pcred.pcr_uid = ap->a_cred->cr_uid; pcred.pcr_ngroups = ap->a_cred->cr_ngroups; bcopy(ap->a_cred->cr_groups, pcred.pcr_groups, NGROUPS * sizeof(gid_t)); aiov[0].iov_base = (caddr_t) &pcred; aiov[0].iov_len = sizeof(pcred); aiov[1].iov_base = pt->pt_arg; aiov[1].iov_len = pt->pt_size; auio.uio_iov = aiov; auio.uio_iovcnt = 2; auio.uio_rw = UIO_WRITE; auio.uio_segflg = UIO_SYSSPACE; auio.uio_td = td; auio.uio_offset = 0; auio.uio_resid = aiov[0].iov_len + aiov[1].iov_len; error = sosend(so, NULL, &auio, NULL, NULL, 0, td); if (error) goto bad; len = sizeof(int); sbinit(&sio, len); do { struct mbuf *m; int flags; flags = MSG_WAITALL; error = soreceive(so, NULL, NULL, &sio, &cm, &flags); if (error) goto bad; /* * Grab an error code from the mbuf. */ if ((m = sio.sb_mb) != NULL) { m = m_pullup(m, sizeof(int)); /* Needed? */ if (m) { error = *(mtod(m, int *)); m_freem(m); } else { error = EINVAL; } } else {
static int lua_dir(lua_State *L) { int k = 0; const char *s = luaL_checkstring(L, 1); #ifdef _WIN32 SB sb; struct _finddata_t info; long hfind; /* special cases */ lua_createtable(L, 0, 0); if ((s[0]=='/' || s[0]=='\\') && (s[1]=='/' || s[1]=='\\') && !s[2]) { int drive; hfind = GetLogicalDrives(); for (drive='A'; drive<='Z'; drive++) if (hfind & (1<<(drive-'A'))) { lua_pushfstring(L, "%c:/", drive); lua_rawseti(L, -2, ++k); } } else if (dirp(L, 1)) { lua_pushliteral(L, ".."); lua_rawseti(L, -2, ++k); } else { lua_pushnil(L); return 1; } /* files */ sbinit(&sb); sbaddn(&sb, s, strlen(s)); if (sb.len>0 && sb.buffer[sb.len-1]!='/' && sb.buffer[sb.len-1]!='\\') sbadd1(&sb, '/'); sbaddn(&sb, "*.*", 3); sbadd1(&sb, 0); hfind = _findfirst(sb.buffer, &info); if (hfind != -1) { do { if (strcmp(".",info.name) && strcmp("..",info.name)) { lua_pushstring(L, info.name); lua_rawseti(L, -2, ++k); } } while ( _findnext(hfind, &info) != -1 ); _findclose(hfind); } sbfree(&sb); #else DIR *dirp; struct dirent *d; dirp = opendir(s); if (dirp) { lua_createtable(L, 0, 0); while ((d = readdir(dirp))) { int n = NAMLEN(d); lua_pushlstring(L, d->d_name, n); lua_rawseti(L, -2, ++k); } closedir(dirp); } else lua_pushnil(L); #endif return 1; }
static int concat_fname(lua_State *L, const char *fname) { const char *from = lua_tostring(L, -1); #ifdef _WIN32 const char *s; SB sb; sbinit(&sb); sbaddn(&sb, from, strlen(from)); if (fname==0) return sbpush(L, &sb); /* Handle absolute part of fname */ if (fname[0]=='/' || fname[0]=='\\') { if (fname[1]=='/' || fname[1]=='\\') { sb.len = 0; /* Case //abcd */ sbaddn(&sb, "//", 2); } else { char drive; if (sb.len >= 2 && sb.buffer[1]==':' /* Case "/abcd" */ && isalpha((unsigned char)(sb.buffer[0])) ) drive = sb.buffer[0]; else drive = _getdrive() + 'A' - 1; sb.len = 0; sbadd1(&sb, drive); sbaddn(&sb, ":/", 2); } } else if (fname[0] && /* Case "x:abcd" */ isalpha((unsigned char)(fname[0])) && fname[1]==':') { if (fname[2]!='/' && fname[2]!='\\') { if (sb.len < 2 || sb.buffer[1]!=':' || !isalpha((unsigned char)(sb.buffer[0])) || (toupper((unsigned char)sb.buffer[0]) != toupper((unsigned char)fname[0]) ) ) { int l; char drv[4]; sb.len = 0; drv[0]=fname[0]; drv[1]=':'; drv[2]='.'; drv[3]=0; l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0); if (l > sb.maxlen) { sbgrow(&sb, l+1); l = GetFullPathNameA(drv, sb.maxlen, sb.buffer, 0); } if (l <= 0) sbaddn(&sb, drv, 3); else sb.len += l; } fname += 2; } else { sb.len = 0; /* Case "x:/abcd" */ sbadd1(&sb, toupper((unsigned char)fname[0])); sbaddn(&sb, ":/", 2); fname += 2; while (*fname == '/' || *fname == '\\') fname += 1; } } /* Process path components */ for (;;) { while (*fname=='/' || *fname=='\\') fname ++; if (*fname == 0) return sbpush(L, &sb); if (fname[0]=='.') { if (fname[1]=='/' || fname[1]=='\\' || fname[1]==0) { fname += 1; continue; } if (fname[1]=='.') if (fname[2]=='/' || fname[2]=='\\' || fname[2]==0) { size_t l; fname += 2; lua_pushcfunction(L, lua_dirname); sbpush(L, &sb); lua_call(L, 1, 1); s = lua_tolstring(L, -1, &l); sbinit(&sb); sbaddn(&sb, s, l); lua_pop(L, 1); continue; } } if (sb.len==0 || (sb.buffer[sb.len-1]!='/' && sb.buffer[sb.len-1]!='\\') ) sbadd1(&sb, '/'); while (*fname && *fname!='/' && *fname!='\\') sbadd1(&sb, *fname++); } #else SB sb; sbinit(&sb); if (fname && fname[0]=='/') sbadd1(&sb, '/'); else sbaddn(&sb, from, strlen(from)); for (;;) { while (fname && fname[0]=='/') fname++; if (!fname || !fname[0]) { sbadd1(&sb, '/'); while (sb.len > 1 && sb.buffer[sb.len-1]=='/') sb.len --; return sbpush(L, &sb); } if (fname[0]=='.') { if (fname[1]=='/' || fname[1]==0) { fname +=1; continue; } if (fname[1]=='.') if (fname[2]=='/' || fname[2]==0) { fname +=2; while (sb.len > 0 && sb.buffer[sb.len-1]=='/') sb.len --; while (sb.len > 0 && sb.buffer[sb.len-1]!='/') sb.len --; continue; } } if (sb.len == 0 || sb.buffer[sb.len-1] != '/') sbadd1(&sb, '/'); while (*fname!=0 && *fname!='/') sbadd1(&sb, *fname++); } #endif }
static int lua_dirname(lua_State *L) { const char *fname = luaL_checkstring(L, 1); #ifdef _WIN32 const char *s; const char *p; SB sb; sbinit(&sb); /* Handle leading drive specifier */ if (isalpha((unsigned char)fname[0]) && fname[1]==':') { sbadd1(&sb, *fname++); sbadd1(&sb, *fname++); } /* Search last non terminal / or \ */ p = 0; s = fname; while (*s) { if ((s[0]=='\\' || s[0]=='/') && (s[1] && s[1]!='/' && s[1]!='\\') ) p = s; s++; } /* Cannot find non terminal / or \ */ if (p == 0) { if (sb.len > 0) { if (fname[0]==0 || fname[0]=='/' || fname[0]=='\\') sbadd1(&sb, '/'); return sbpush(L, &sb); } else { if (fname[0]=='/' || fname[0]=='\\') return sbsetpush(L, &sb, "//"); else return sbsetpush(L, &sb, "."); } } /* Single leading slash */ if (p == fname) { sbadd1(&sb, '/'); return sbpush(L, &sb); } /* Backtrack all slashes */ while (p>fname && (p[-1]=='/' || p[-1]=='\\')) p--; /* Multiple leading slashes */ if (p == fname) return sbsetpush(L, &sb, "//"); /* Regular case */ s = fname; do { sbadd1(&sb, *s++); } while (s<p); return sbpush(L, &sb); #else const char *s = fname; const char *p = 0; SB sb; sbinit(&sb); while (*s) { if (s[0]=='/' && s[1] && s[1]!='/') p = s; s++; } if (!p) { if (fname[0]=='/') return sbsetpush(L, &sb, fname); else return sbsetpush(L, &sb, "."); } s = fname; do { sbadd1(&sb, *s++); } while (s<p); return sbpush(L, &sb); #endif }
static int lua_basename(lua_State *L) { const char *fname = luaL_checkstring(L, 1); const char *suffix = luaL_optstring(L, 2, 0); #ifdef _WIN32 int sl; const char *p, *s; SB sb; sbinit(&sb); /* Special cases */ if (fname[0] && fname[1]==':') { sbaddn(&sb, fname, 2); fname += 2; if (fname[0]=='/' || fname[0]=='\\') sbadd1(&sb, '/'); while (fname[0]=='/' || fname[0]=='\\') fname += 1; if (fname[0]==0) return sbpush(L, &sb); sb.len = 0; } /* Position p after last nontrivial slash */ s = p = fname; while (*s) { if ((s[0]=='\\' || s[0]=='/') && (s[1] && s[1]!='/' && s[1]!='\\' ) ) p = s + 1; s++; } /* Copy into buffer */ while (*p && *p!='/' && *p!='\\') sbadd1(&sb, *p++); /* Process suffix */ if (suffix==0 || suffix[0]==0) return sbpush(L, &sb); if (suffix[0]=='.') suffix += 1; if (suffix[0]==0) return sbpush(L, &sb); sl = strlen(suffix); if (sb.len > sl) { s = sb.buffer + sb.len - (sl + 1); if (s[0]=='.' && _strnicmp(s+1,suffix, sl)==0) sb.len = s - sb.buffer; } return sbpush(L, &sb); #else int sl; const char *s, *p; SB sb; sbinit(&sb); /* Position p after last nontrivial slash */ s = p = fname; while (*s) { if (s[0]=='/' && s[1] && s[1]!='/') p = s + 1; s++; } /* Copy into buffer */ while (*p && *p!='/') sbadd1(&sb, *p++); /* Process suffix */ if (suffix==0 || suffix[0]==0) return sbpush(L, &sb); if (suffix[0]=='.') suffix += 1; if (suffix[0]==0) return sbpush(L, &sb); sl = strlen(suffix); if (sb.len > sl) { s = sb.buffer + sb.len - (sl + 1); if (s[0]=='.' && strncmp(s+1,suffix, sl)==0) sb.len = s - sb.buffer; } return sbpush(L, &sb); #endif }
/* * When incoming data is appended to the socket, we get notified here. * This is also called whenever a significant event occurs for the socket. * Our original caller may have queued this even some time ago and * we cannot trust that he even still exists. The node however is being * held with a reference by the queueing code and guarantied to be valid. */ static void ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int arg2) { struct socket *so = arg1; const priv_p priv = NG_NODE_PRIVATE(node); struct ng_mesg *response; int flags, error; crit_enter(); /* so = priv->so; *//* XXX could have derived this like so */ KASSERT(so == priv->so, ("%s: wrong socket", __func__)); /* Allow next incoming event to be queued. */ atomic_store_rel_int(&priv->fn_sent, 0); /* Check whether a pending connect operation has completed */ if (priv->flags & KSF_CONNECTING) { if ((error = so->so_error) != 0) { so->so_error = 0; soclrstate(so, SS_ISCONNECTING); } if (!(so->so_state & SS_ISCONNECTING)) { NG_MKMESSAGE(response, NGM_KSOCKET_COOKIE, NGM_KSOCKET_CONNECT, sizeof(int32_t), M_WAITOK | M_NULLOK); if (response != NULL) { response->header.flags |= NGF_RESP; response->header.token = priv->response_token; *(int32_t *)response->data = error; /* * send an async "response" message * to the node that set us up * (if it still exists) */ NG_SEND_MSG_ID(error, node, response, priv->response_addr, 0); } priv->flags &= ~KSF_CONNECTING; } } /* Check whether a pending accept operation has completed */ if (priv->flags & KSF_ACCEPTING) { error = ng_ksocket_check_accept(priv); if (error != EWOULDBLOCK) priv->flags &= ~KSF_ACCEPTING; if (error == 0) ng_ksocket_finish_accept(priv); } /* * If we don't have a hook, we must handle data events later. When * the hook gets created and is connected, this upcall function * will be called again. */ if (priv->hook == NULL) { crit_exit(); return; } /* Read and forward available mbuf's */ while (1) { struct sockaddr *sa = NULL; struct sockbuf sio; struct mbuf *n; sbinit(&sio, 1000000000); flags = MSG_DONTWAIT; /* Try to get next packet from socket */ error = soreceive(so, ((so->so_state & SS_ISCONNECTED) ? NULL : &sa), NULL, &sio, NULL, &flags); if (error) break; /* See if we got anything */ if (sio.sb_mb == NULL) { if (sa != NULL) kfree(sa, M_SONAME); break; } /* * Don't trust the various socket layers to get the * packet header and length correct (e.g. kern/15175). * * Also, do not trust that soreceive() will clear m_nextpkt * for us (e.g. kern/84952, kern/82413). */ sio.sb_mb->m_pkthdr.csum_flags = 0; sio.sb_mb->m_pkthdr.len = 0; for (n = sio.sb_mb; n != NULL; n = n->m_next) { sio.sb_mb->m_pkthdr.len += n->m_len; n->m_nextpkt = NULL; } /* Put peer's socket address (if any) into a tag */ if (sa != NULL) { struct sa_tag *stag; stag = (struct sa_tag *)m_tag_alloc(NGM_KSOCKET_COOKIE, NG_KSOCKET_TAG_SOCKADDR, sizeof(ng_ID_t) + sa->sa_len, MB_DONTWAIT); if (stag == NULL) { kfree(sa, M_SONAME); goto sendit; } bcopy(sa, &stag->sa, sa->sa_len); kfree(sa, M_SONAME); stag->id = NG_NODE_ID(node); m_tag_prepend(sio.sb_mb, &stag->tag); } sendit: /* Forward data with optional peer sockaddr as packet tag */ NG_SEND_DATA_ONLY(error, priv->hook, sio.sb_mb); } /* * If the peer has closed the connection, forward a 0-length mbuf * to indicate end-of-file. */ if (so->so_state & SS_CANTRCVMORE && !(priv->flags & KSF_EOFSEEN)) { struct mbuf *m; MGETHDR(m, MB_DONTWAIT, MT_DATA); if (m != NULL) { m->m_len = m->m_pkthdr.len = 0; NG_SEND_DATA_ONLY(error, priv->hook, m); } priv->flags |= KSF_EOFSEEN; } crit_exit(); }