/* * Create a new pair of proxy_connection entries, one for each * socket file descriptor involved in the proxy. We are given * the client fd, and we should derive our own server fd by connecting * to the server given by server_addr/server_port. Return true * on success and false on failure to connect to server. */ static bool proxy_entry_new(struct proxy_connection **list, struct event_set *es, const struct sockaddr_in server_addr, const socket_descriptor_t sd_client, struct buffer *initial_data, const char *journal_dir) { socket_descriptor_t sd_server; int status; struct proxy_connection *pc; struct proxy_connection *cp; /* connect to port share server */ if ((sd_server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { msg(M_WARN|M_ERRNO, "PORT SHARE PROXY: cannot create socket"); return false; } status = openvpn_connect(sd_server,(const struct sockaddr *) &server_addr, 5, NULL); if (status) { msg(M_WARN, "PORT SHARE PROXY: connect to port-share server failed"); openvpn_close_socket(sd_server); return false; } dmsg(D_PS_PROXY_DEBUG, "PORT SHARE PROXY: connect to port-share server succeeded"); set_nonblock(sd_client); set_nonblock(sd_server); /* allocate 2 new proxy_connection objects */ ALLOC_OBJ_CLEAR(pc, struct proxy_connection); ALLOC_OBJ_CLEAR(cp, struct proxy_connection); /* client object */ pc->defined = true; pc->next = cp; pc->counterpart = cp; pc->buf = *initial_data; pc->buffer_initial = true; pc->rwflags = EVENT_UNDEF; pc->sd = sd_client; /* server object */ cp->defined = true; cp->next = *list; cp->counterpart = pc; cp->buf = alloc_buf(PROXY_CONNECTION_BUFFER_SIZE); cp->buffer_initial = false; cp->rwflags = EVENT_UNDEF; cp->sd = sd_server; /* add to list */ *list = pc; /* add journal entry */ if (journal_dir) { journal_add(journal_dir, pc, cp); } dmsg(D_PS_PROXY_DEBUG, "PORT SHARE PROXY: NEW CONNECTION [c=%d s=%d]", (int)sd_client, (int)sd_server); /* set initial i/o states */ proxy_connection_io_requeue(pc, EVENT_READ, es); proxy_connection_io_requeue(cp, EVENT_READ|EVENT_WRITE, es); return true; }
int bof(buffer * str) { buffer * dst = alloc_buf((24)); str_copy(dst, str); return 1; }
static char * common_flags_to_string (FlagType flags, int object_type, FlagBitsType *flagbits, int n_flagbits) { int len; int i; FlagHolder fh, savef; char *buf, *bp; unknown_flag_t *u; fh.Flags = flags; #ifndef FLAG_TEST switch (object_type) { case VIA_TYPE: CLEAR_FLAG (VIAFLAG, &fh); break; case RATLINE_TYPE: CLEAR_FLAG (RATFLAG, &fh); break; case PIN_TYPE: CLEAR_FLAG (PINFLAG, &fh); break; } #endif savef = fh; len = 3; /* for "()\0" */ for (i = 0; i < n_flagbits; i++) if ((flagbits[i].object_types & object_type) && (TEST_FLAG (flagbits[i].mask, &fh))) { len += flagbits[i].nlen + 1; CLEAR_FLAG (flagbits[i].mask, &fh); } if (TEST_ANY_THERMS (&fh)) { len += sizeof ("thermal()"); for (i = 0; i < MAX_LAYER; i++) if (TEST_THERM (i, &fh)) len += printed_int_length (i, GET_THERM (i, &fh)) + 1; } if (flags.q > 0) { len += sizeof ("shape(.)"); if (flags.q > 9) len+=2; } if (flags.int_conn_grp > 0) { len += sizeof ("intconn(.)"); if (flags.q > 9) len++; if (flags.q > 99) len++; } for(u = flags.unknowns; u != NULL; u = u->next) len += strlen(u->str)+1; bp = buf = alloc_buf (len + 2); *bp++ = '"'; fh = savef; for (i = 0; i < n_flagbits; i++) if (flagbits[i].object_types & object_type && (TEST_FLAG (flagbits[i].mask, &fh))) { if (bp != buf + 1) *bp++ = ','; strcpy (bp, flagbits[i].name); bp += flagbits[i].nlen; CLEAR_FLAG (flagbits[i].mask, &fh); } if (TEST_ANY_THERMS (&fh)) { if (bp != buf + 1) *bp++ = ','; strcpy (bp, "thermal"); bp += strlen ("thermal"); grow_layer_list (0); for (i = 0; i < MAX_LAYER; i++) if (TEST_THERM (i, &fh)) set_layer_list (i, GET_THERM (i, &fh)); strcpy (bp, print_layer_list ()); bp += strlen (bp); } if (flags.q > 0) { if (bp != buf + 1) *bp++ = ','; bp += sprintf(bp, "shape(%d)", flags.q); } if (flags.int_conn_grp > 0) { if (bp != buf + 1) *bp++ = ','; bp += sprintf(bp, "intconn(%d)", flags.int_conn_grp); } for(u = flags.unknowns; u != NULL; u = u->next) { int len; len = strlen(u->str); if (bp != buf + 1) *bp++ = ','; memcpy(bp, u->str, len); bp += len; } *bp++ = '"'; *bp = 0; return buf; }
/* * This function runs in the context of the background proxy process. * Receive a control message from the parent (sent by the port_share_sendmsg * function above) and act on it. Return false if the proxy process should * exit, true otherwise. */ static bool control_message_from_parent (const socket_descriptor_t sd_control, struct proxy_connection **list, struct event_set *es, const struct sockaddr_in server_addr, const int max_initial_buf, const char *journal_dir) { /* this buffer needs to be large enough to handle the largest buffer that might be returned by the link_socket_read call in read_incoming_link. */ struct buffer buf = alloc_buf (max_initial_buf); struct msghdr mesg; struct cmsghdr* h; struct iovec iov[2]; char command = 0; ssize_t status; int ret = true; CLEAR (mesg); iov[0].iov_base = &command; iov[0].iov_len = sizeof (command); iov[1].iov_base = BPTR (&buf); iov[1].iov_len = BCAP (&buf); mesg.msg_iov = iov; mesg.msg_iovlen = 2; mesg.msg_controllen = cmsg_size (); mesg.msg_control = (char *) malloc (mesg.msg_controllen); check_malloc_return (mesg.msg_control); mesg.msg_flags = 0; h = CMSG_FIRSTHDR(&mesg); h->cmsg_len = CMSG_LEN(sizeof(socket_descriptor_t)); h->cmsg_level = SOL_SOCKET; h->cmsg_type = SCM_RIGHTS; *((socket_descriptor_t*)CMSG_DATA(h)) = SOCKET_UNDEFINED; status = recvmsg (sd_control, &mesg, MSG_NOSIGNAL); if (status != -1) { if ( h == NULL || h->cmsg_len != CMSG_LEN(sizeof(socket_descriptor_t)) || h->cmsg_level != SOL_SOCKET || h->cmsg_type != SCM_RIGHTS ) { msg (M_WARN, "PORT SHARE PROXY: received unknown message"); } else { const socket_descriptor_t received_fd = *((socket_descriptor_t*)CMSG_DATA(h)); dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: RECEIVED sd=%d", (int)received_fd); if (status >= 2 && command == COMMAND_REDIRECT) { buf.len = status - 1; if (proxy_entry_new (list, es, server_addr, received_fd, &buf, journal_dir)) { CLEAR (buf); /* we gave the buffer to proxy_entry_new */ } else { openvpn_close_socket (received_fd); } } else if (status >= 1 && command == COMMAND_EXIT) { dmsg (D_PS_PROXY_DEBUG, "PORT SHARE PROXY: RECEIVED COMMAND_EXIT"); openvpn_close_socket (received_fd); /* null socket */ ret = false; } } } free (mesg.msg_control); free_buf (&buf); return ret; }
static FlagType common_string_to_flags (const char *flagstring, int (*error) (const char *msg), FlagBitsType *flagbits, int n_flagbits) { const char *fp, *ep; int flen; FlagHolder rv; int i; rv.Flags = empty_flags; if (error == 0) error = error_ignore; if (flagstring == NULL) return empty_flags; fp = ep = flagstring; if (*fp == '"') ep = ++fp; while (*ep && *ep != '"') { int found = 0; for (ep = fp; *ep && *ep != ',' && *ep != '"' && *ep != '('; ep++) ; flen = ep - fp; if (*ep == '(') ep = parse_layer_list (ep + 1, error); if (flen == 7 && memcmp (fp, "thermal", 7) == 0) { for (i = 0; i < MAX_LAYER && i < num_layers; i++) if (layers[i]) ASSIGN_THERM (i, layers[i], &rv); } else if (flen == 5 && memcmp (fp, "shape", 5) == 0) { rv.Flags.q=atoi(fp+6); } else if (flen == 7 && memcmp (fp, "intconn", 7) == 0) { rv.Flags.int_conn_grp=atoi(fp+8); } else { for (i = 0; i < n_flagbits; i++) if (flagbits[i].nlen == flen && memcmp (flagbits[i].name, fp, flen) == 0) { found = 1; SET_FLAG (flagbits[i].mask, &rv); break; } if (!found) { const char *fmt = "Unknown flag: \"%.*s\" ignored"; unknown_flag_t *u; char *msg, *s; /* include () */ s = fp + flen; if (*s == '(') { while(*s != ')') { flen++; s++; } } if (*s == ')') flen++; msg = alloc_buf (strlen (fmt) + flen); sprintf (msg, fmt, flen, fp); error (msg); u = malloc(sizeof(unknown_flag_t)); u->str = strndup(fp, flen); u->next = NULL; /* need to append, to keep order of flags */ if (rv.Flags.unknowns != NULL) { unknown_flag_t *n; for(n = rv.Flags.unknowns; n->next != NULL; n = n->next) ; n->next = u; } else rv.Flags.unknowns = u; } } fp = ep + 1; } return rv.Flags; }