static void add_cb(evhtp_request_t* req, void* a) { if (req->method != htp_method_POST) { evhtp_send_reply(req, EVHTP_RES_METHNALLOWED); return; } size_t len; auto buf = extract_body(req, &len); if (!buf) { evhtp_send_reply(req, EVHTP_RES_500); return; } StaticJsonBuffer<10 * 1024> jsonBuffer; auto& root = jsonBuffer.parseObject(buf); if (!root.success()) { const auto err = "JsonBuffer::parseObject() failed"; evbuffer_add(req->buffer_out, err, strlen(err)); evhtp_send_reply(req, EVHTP_RES_500); return; } const char* id = root["id"]; evbuffer_add(req->buffer_out, "OK:", 3); evbuffer_add(req->buffer_out, id, strlen(id)); evhtp_send_reply(req, EVHTP_RES_OK); }
static void add_cb(evhtp_request_t* req, void* a) { if (req->method != htp_method_POST) { evhtp_send_reply(req, EVHTP_RES_METHNALLOWED); return; } size_t len; auto buf = extract_body(req, &len); if (!buf) { evhtp_send_reply(req, EVHTP_RES_500); return; } char* endptr; JsonValue value; JsonAllocator allocator; int status = jsonParse(buf, &endptr, &value, allocator); if (status != JSON_OK) { evhtp_send_reply(req, EVHTP_RES_500); return; } evbuffer_add(req->buffer_out, "OK:", 3); // TODO: how to retrieve id? // evbuffer_add(req->buffer_out, id.c_str(), id.size()); evhtp_send_reply(req, EVHTP_RES_OK); }
/* * Read client response from an HTTP request into a buffer. Return the number of * characters written to buf (EXCLUDING null character); */ void extract_client_response(struct HTTPObject *h, EthernetClient client){ extract_status_code(h, client); skip_http_headers(client); extract_body(h, client); // Clean up the connection client.flush(); client.stop(); }
/* * test for occurrence of RFC1918 IP address in SDP */ static int sdp_1918(struct sip_msg* msg) { str body, ip; int pf; if (extract_body(msg, &body) == -1) { LOG(L_ERR,"ERROR: sdp_1918: cannot extract body from msg!\n"); return 0; } if (extract_mediaip(&body, &ip, &pf) == -1) { LOG(L_ERR, "ERROR: sdp_1918: can't extract media IP from the SDP\n"); return 0; } if (pf != AF_INET || isnulladdr(&ip, pf)) return 0; return (is1918addr(&ip) == 1) ? 1 : 0; }
/* ** reply_by_mail() invokes sendmail on Unix or mail on VMS to send ** a comment from the users to the owner */ PUBLIC void reply_by_mail ARGS4( char *, mail_address, char *, filename, CONST char *, title, CONST char *, refid) { #ifndef NO_ANONYMOUS_EMAIL static char *personal_name = NULL; #endif char user_input[LINESIZE]; FILE *fd, *fp; char *label = NULL; char *from_address = NULL; char *cc_address = NULL; char *to_address = NULL; char *the_subject = NULL; char *ccaddr = NULL; char *keywords = NULL; char *searchpart = NULL; char *body = NULL; char *cp = NULL, *cp1 = NULL; int i; int c = 0; /* user input */ char my_tmpfile[LY_MAXPATH]; char default_subject[MAX_SUBJECT + 10]; #if USE_VMS_MAILER char *command = NULL; BOOLEAN isPMDF = LYMailPMDF(); char hdrfile[LY_MAXPATH]; FILE *hfd = 0; #else #if !CAN_PIPE_TO_MAILER char tmpfile2[LY_MAXPATH]; #endif char buf[4096]; /* 512 */ char *header = NULL; int n; #endif /* USE_VMS_MAILER */ CTRACE((tfp, "reply_by_mail(\"%s\", \"%s\", \"%s\", \"%s\")\n", NONNULL(mail_address), NONNULL(filename), NONNULL(title), NONNULL(refid))); term_letter = FALSE; if (!LYSystemMail()) return; if (isEmpty(mail_address)) { HTAlert(NO_ADDRESS_IN_MAILTO_URL); return; } StrAllocCopy(to_address, mail_address); if ((fd = LYOpenTemp(my_tmpfile, ".txt", "w")) == NULL) { HTAlert(MAILTO_URL_TEMPOPEN_FAILED); return; } #if USE_VMS_MAILER if (isPMDF) { if ((hfd = LYOpenTemp(hdrfile, ".txt", "w")) == NULL) { HTAlert(MAILTO_URL_TEMPOPEN_FAILED); return; } } #endif /* VMS */ default_subject[0] = '\0'; /* * Check for a ?searchpart. - FM */ if ((cp = strchr(to_address, '?')) != NULL) { StrAllocCopy(searchpart, cp); *cp = '\0'; cp = (searchpart + 1); if (*cp != '\0') { /* * Seek and handle a subject=foo. - FM */ extract_subject(default_subject, searchpart); /* * Seek and handle to=address(es) fields. * Appends to address. - FM */ extract_field(&to_address, searchpart, "to="); /* * Seek and handle cc=address(es) fields. Excludes * Bcc=address(es) as unsafe. We may append our own * cc (below) as a list for the actual mailing. - FM */ extract_field(&ccaddr, searchpart, "cc="); /* * Seek and handle keywords=term(s) fields. - FM */ extract_field(&keywords, searchpart, "keywords="); if (keywords != NULL) { if (*keywords != '\0') { SafeHTUnEscape(keywords); } else { FREE(keywords); } } /* * Seek and handle body=foo fields. - FM */ extract_body(&body, searchpart); FREE(searchpart); } } if (convert_explorer(to_address)) { HTAlert(NO_ADDRESS_IN_MAILTO_URL); goto cancelled; } if (ccaddr != NULL) { if (convert_explorer(ccaddr)) { FREE(ccaddr); } } /* * Unescape the address and ccaddr fields. - FM */ SafeHTUnEscape(to_address); if (ccaddr != NULL) { SafeHTUnEscape(ccaddr); } /* * Set the default subject. - FM */ if (isEmpty(default_subject) && !isEmpty(title)) { strncpy(default_subject, title, MAX_SUBJECT); default_subject[MAX_SUBJECT] = '\0'; } /* * Use ^G to cancel mailing of comment * and don't let SIGINTs exit lynx. */ signal(SIGINT, terminate_letter); #if USE_VMS_MAILER if (isPMDF || !body) { /* * Put the X-URL and X-Mailer lines in the hdrfile * for PMDF or my_tmpfile for VMS MAIL. - FM */ fprintf((isPMDF ? hfd : fd), "X-URL: %s%s\n", isEmpty(filename) ? STR_MAILTO_URL : filename, isEmpty(filename) ? to_address : ""); fprintf((isPMDF ? hfd : fd), "X-Mailer: %s, Version %s\n", LYNX_NAME, LYNX_VERSION); #ifdef NO_ANONYMOUS_EMAIL if (!isPMDF) { fprintf(fd, "\n"); } #endif /* NO_ANONYMOUS_EMAIL */ } #else /* Unix/DOS/Windows */ /* * Put the To: line in the header. */ #ifndef DOSPATH asprintf(&header, "To: %s\n", to_address); if (!header) { fprintf(stderr, "Out of memory, you lose!\n"); exit(1); } #endif /* * Put the Mime-Version, Content-Type and * Content-Transfer-Encoding in the header. * This assumes that the same character set is used * for composing the mail which is currently selected * as display character set... * Don't send a charset if we have a CJK character set * selected, since it may not be appropriate for mail... * Also don't use an unofficial "x-" charset. * Also if the charset would be "us-ascii" (7-bit replacements * selected, don't send any MIME headers. - kw */ if (strncasecomp(LYCharSet_UC[current_char_set].MIMEname, "us-ascii", 8) != 0) { StrAllocCat(header, "Mime-Version: 1.0\n"); if (!LYHaveCJKCharacterSet && strncasecomp(LYCharSet_UC[current_char_set].MIMEname, "x-", 2) != 0) { HTSprintf(&header, "Content-Type: text/plain; charset=%s\n", LYCharSet_UC[current_char_set].MIMEname); } StrAllocCat(header, "Content-Transfer-Encoding: 8bit\n"); } /* * Put the X-URL and X-Mailer lines in the header. */ if (!isEmpty(filename)) { HTSprintf(&header, "X-URL: %s\n", filename); } else { HTSprintf(&header, "X-URL: mailto:%s\n", to_address); } HTSprintf(&header, "X-Mailer: %s, Version %s\n", LYNX_NAME, LYNX_VERSION); if (!isEmpty(refid)) { HTSprintf(&header, "In-Reply-To: <%s>\n", refid); } #endif /* VMS */ /* * Clear the screen and inform the user. */ LYclear(); LYmove(2,0); scrollok(LYwin, TRUE); /* Enable scrolling. */ if (body) LYaddstr(SENDING_MESSAGE_WITH_BODY_TO); else LYaddstr(SENDING_COMMENT_TO); show_addresses(to_address); if ( #if USE_VMS_MAILER (isPMDF == TRUE) && #endif /* VMS */ (cp = ccaddr) != NULL) { if (strchr(cp, ',') != NULL) { LYaddstr(WITH_COPIES_TO); } else { LYaddstr(WITH_COPY_TO); } show_addresses(ccaddr); } LYaddstr(CTRL_G_TO_CANCEL_SEND); #if USE_VMS_MAILER if (isPMDF || !body) { #endif /* USE_VMS_MAILER */ #ifndef NO_ANONYMOUS_EMAIL /* * Get the user's personal name. */ LYaddstr(ENTER_NAME_OR_BLANK); #if USE_VMS_MAILER if (isPMDF) { label = "Personal_name: "; } else { label = "X-Personal_name: "; } #else label = "X-Personal_Name: "; #endif /* USE_VMS_MAILER */ if (!header_prompt(label, &personal_name, LINESIZE)) { goto cancelled; } if (*personal_name) { #if USE_VMS_MAILER fprintf((isPMDF ? hfd : fd), "%s: %s\n", label, personal_name); #else HTSprintf(&header, "%s: %s\n", label, personal_name); #endif /* VMS */ } /* * Get the user's return address. */ LYaddstr(ENTER_MAIL_ADDRESS_OR_OTHER); LYaddstr(MEANS_TO_CONTACT_FOR_RESPONSE); #if USE_VMS_MAILER if (isPMDF) { label = "From"; } else { label = "X-From"; } #else label = "From"; #endif /* VMS */ /* Add the personal mail address if there is one. */ if (personal_mail_address) StrAllocCopy(from_address, personal_mail_address); if (!header_prompt(label, &from_address, LINESIZE)) { goto cancelled; } #if USE_VMS_MAILER if (*from_address) { fprintf(isPMDF ? hfd : fd, "%s: %s\n", label, from_address); } if (!isPMDF) { fprintf(fd, "\n"); } #else HTSprintf(&header, "%s: %s\n", label, from_address); #endif /* USE_VMS_MAILER */ #endif /* !NO_ANONYMOUS_EMAIL */ #if USE_VMS_MAILER } #endif /* USE_VMS_MAILER */ /* * Get the subject line. */ LYaddstr(ENTER_SUBJECT_LINE); label = "Subject"; if (*default_subject) { StrAllocCopy(the_subject, default_subject); } else if (!isEmpty(filename)) { HTSprintf(&the_subject, "%s", filename); } else { HTSprintf(&the_subject, "mailto:%s", to_address); } if (!header_prompt(label, &the_subject, MAX_SUBJECT)) { goto cancelled; } /* * Offer a CC line, if permitted. - FM */ if (!LYNoCc) { LYaddstr(ENTER_ADDRESS_FOR_CC); LYaddstr(BLANK_FOR_NO_COPY); if (personal_mail_address) StrAllocCopy(cc_address, personal_mail_address); if (!header_prompt("Cc", &cc_address, LINESIZE)) { goto cancelled; } comma_append(&ccaddr, cc_address); } #if !USE_VMS_MAILER HTSprintf(&header, "%s: %s\n", label, the_subject); #if !CAN_PIPE_TO_MAILER if (*to_address) { HTSprintf(&header, "To: %s\n", to_address); } #endif /* ** Add the Cc: header. - FM */ if (!isEmpty(ccaddr)) { HTSprintf(&header, "Cc: %s\n", ccaddr); } /* ** Add the Keywords: header. - FM */ if (!isEmpty(keywords)) { HTSprintf(&header, "Keywords: %s\n", keywords); } /* * Terminate the header. */ StrAllocCat(header, "\n"); CTRACE((tfp,"**header==\n%s",header)); #endif /* !VMS */ if (!no_editor && !isEmpty(editor)) { if (body) { cp1 = body; while((cp = strchr(cp1, '\n')) != NULL) { *cp++ = '\0'; fprintf(fd, "%s\n", cp1); cp1 = cp; } } else if (strcmp(HTLoadedDocumentURL(), "")) { /* * Ask if the user wants to include the original message. */ BOOLEAN is_preparsed = (BOOL) (LYPreparsedSource && HTisDocumentSource()); if (HTConfirm(is_preparsed ? INC_PREPARSED_MSG_PROMPT : INC_ORIG_MSG_PROMPT) == YES) { print_wwwfile_to_fd(fd, (BOOL) !is_preparsed); } } LYCloseTempFP(fd); /* Close the tmpfile. */ scrollok(LYwin,FALSE); /* Stop scrolling. */ if (term_letter || LYCharIsINTERRUPT(c)) goto cleanup; /* * Spawn the users editor on the mail file */ edit_temporary_file(my_tmpfile, "", SPAWNING_EDITOR_FOR_MAIL); } else if (body) { /* * Let user review the body. - FM */ LYclear(); LYmove(0,0); LYaddstr(REVIEW_MESSAGE_BODY); LYrefresh(); cp1 = body; i = (LYlines - 5); while((cp = strchr(cp1, '\n')) != NULL) { if (i <= 0) { LYaddstr(RETURN_TO_CONTINUE); LYrefresh(); c = LYgetch(); LYaddstr("\n"); if (term_letter || LYCharIsINTERRUPT(c)) { goto cancelled; } i = (LYlines - 2); } *cp++ = '\0'; fprintf(fd, "%s\n", cp1); LYaddstr(cp1); LYaddstr("\n"); cp1 = cp; i--; } while (i >= 0) { LYaddstr("\n"); i--; } LYrefresh(); LYCloseTempFP(fd); /* Close the tmpfile. */ scrollok(LYwin,FALSE); /* Stop scrolling. */ } else { /* * Use the internal line editor for the message. */ LYaddstr(ENTER_MESSAGE_BELOW); LYaddstr(ENTER_PERIOD_WHEN_DONE_A); LYaddstr(ENTER_PERIOD_WHEN_DONE_B); LYaddstr("\n\n"); LYrefresh(); *user_input = '\0'; if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0 || term_letter || STREQ(user_input, ".")) { goto cancelled; } while (!STREQ(user_input, ".") && !term_letter) { LYaddstr("\n"); remove_tildes(user_input); fprintf(fd, "%s\n", user_input); *user_input = '\0'; if (LYgetstr(user_input, VISIBLE, sizeof(user_input), NORECALL) < 0) { goto cancelled; } } fprintf(fd, "\n"); /* Terminate the message. */ LYCloseTempFP(fd); /* Close the tmpfile. */ scrollok(LYwin,FALSE); /* Stop scrolling. */ } #if !USE_VMS_MAILER /* * Ignore CTRL-C on this last question. */ signal(SIGINT, SIG_IGN); #endif /* !VMS */ LYStatusLine = (LYlines - 1); c = HTConfirm (body ? SEND_MESSAGE_PROMPT : SEND_COMMENT_PROMPT); LYStatusLine = -1; if (c != YES) { LYclear(); /* clear the screen */ goto cleanup; } if ((body == NULL && LynxSigFile != NULL) && (fp = fopen(LynxSigFile, TXT_R)) != NULL) { LYStatusLine = (LYlines - 1); if (term_letter) { _user_message(APPEND_SIG_FILE, LynxSigFile); c = 0; } else { char *msg = NULL; HTSprintf0(&msg, APPEND_SIG_FILE, LynxSigFile); c = HTConfirm(msg); FREE(msg); } LYStatusLine = -1; if (c == YES) { if ((fd = fopen(my_tmpfile, TXT_A)) != NULL) { char *buffer = NULL; fputs("-- \n", fd); while (LYSafeGets(&buffer, fp) != NULL) { fputs(buffer, fd); } LYCloseOutput(fd); FREE(buffer); } } LYCloseInput(fp); } LYclear(); /* Clear the screen. */ /* * Send the message. */ #if USE_VMS_MAILER /* * Set the mail command. - FM */ if (isPMDF) { /* * For PMDF, put any keywords and the subject * in the header file and close it. - FM */ if (!isEmpty(keywords)) { fprintf(hfd, "Keywords: %s\n", keywords); } fprintf(hfd, "Subject: %s\n\n", the_subject); LYCloseTempFP(hfd); /* * Now set up the command. - FM */ HTSprintf0(&command, "%s %s %s,%s ", system_mail, system_mail_flags, hdrfile, my_tmpfile); } else { /* * For "generic" VMS MAIL, include the subject in the * command, and ignore any keywords to minimize risk * of them making the line too long or having problem * characters. - FM */ HTSprintf0(&command, "%s %s%s/subject=\"%s\" %s ", system_mail, system_mail_flags, (strncasecomp(system_mail, "MAIL", 4) ? "" : "/noself"), the_subject, my_tmpfile); } vms_append_addrs(&command, to_address, ""); if (!isEmpty(ccaddr)) { vms_append_addrs(&command, ccaddr, "/CC"); } stop_curses(); printf("%s\n\n$ %s\n\n%s", SENDING_COMMENT, command, PLEASE_WAIT); LYSystem(command); /* SENDING COMMENT (VMS) */ FREE(command); LYSleepAlert(); start_curses(); #else /* Unix/DOS/Windows */ /* * Send the tmpfile into sendmail. */ _statusline(SENDING_YOUR_MSG); #if CAN_PIPE_TO_MAILER signal(SIGINT, SIG_IGN); if ((fp = LYPipeToMailer()) == 0) { HTInfoMsg(CANCELLED); } #else if ((fp = LYOpenTemp(tmpfile2, ".txt", "w")) == NULL) { HTAlert(MAILTO_URL_TEMPOPEN_FAILED); } #endif /* CAN_PIPE_TO_MAILER */ if (fp != 0) { fd = fopen(my_tmpfile, TXT_R); if (fd == NULL) { HTInfoMsg(CANCELLED); #if CAN_PIPE_TO_MAILER pclose(fp); #else LYCloseTempFP(fp); #endif /* CAN_PIPE_TO_MAILER */ } else { #if USE_BLAT_MAILER if (!mail_is_blat) fputs(header, fp); #else fputs(header, fp); #endif while ((n = fread(buf, 1, sizeof(buf), fd)) != 0) { fwrite(buf, 1, n, fp); } #if CAN_PIPE_TO_MAILER pclose(fp); #else LYCloseTempFP(fp); /* Close the tmpfile. */ LYSendMailFile ( to_address, tmpfile2, the_subject, ccaddr, SENDING_COMMENT); LYRemoveTemp(tmpfile2); /* Delete the tmpfile. */ #endif /* CAN_PIPE_TO_MAILER */ LYCloseInput(fd); /* Close the tmpfile. */ } } #endif /* USE_VMS_MAILER */ goto cleanup; /* * Come here to cleanup and exit. */ cancelled: HTInfoMsg(CANCELLED); LYCloseTempFP(fd); /* Close the tmpfile. */ scrollok(LYwin,FALSE); /* Stop scrolling. */ cleanup: signal(SIGINT, cleanup_sig); term_letter = FALSE; #if USE_VMS_MAILER while (LYRemoveTemp(my_tmpfile) == 0) ; /* Delete the tmpfile(s). */ if (isPMDF) { LYRemoveTemp(hdrfile); /* Delete the hdrfile. */ } #else FREE(header); LYRemoveTemp(my_tmpfile); /* Delete the tmpfile. */ #endif /* VMS */ FREE(from_address); FREE(the_subject); FREE(cc_address); FREE(to_address); FREE(ccaddr); FREE(keywords); FREE(body); return; }
static int force_rtp_proxy_f(struct sip_msg* msg, char* str1, char* str2) { str body, body1, oldport, oldip, oldip1, newport, newip; int create, port, cldelta; char buf[16]; char *cp; if (msg->first_line.type == SIP_REQUEST && msg->first_line.u.request.method_value == METHOD_INVITE) { create = 1; } else if (msg->first_line.type == SIP_REPLY) { create = 0; } else { return -1; } if (msg->callid == NULL || msg->callid->body.len <= 0) { LOG(L_ERR, "ERROR: force_rtp_proxy: no Call-Id field\n"); return -1; } if (extract_body(msg, &body) == -1 || body.len == 0) return -1; if (extract_mediaip(&body, &oldip) == -1) { LOG(L_ERR, "ERROR: force_rtp_proxy: can't extract media IP from the message\n"); return -1; } body1.s = oldip.s + oldip.len; body1.len = body.s + body.len - body1.s; if (extract_mediaip(&body1, &oldip1) == -1) { oldip1.len = 0; } if (extract_mediaport(&body, &oldport) == -1) { LOG(L_ERR, "ERROR: force_rtp_proxy: can't extract media port from the message\n"); return -1; } cp = send_rtpp_command(&(msg->callid->body), create ? 'U' : 'L', 1); if (cp == NULL) return -1; port = atoi(cp); if (port <= 0 || port > 65535) return -1; newport.s = buf; newport.len = sprintf(buf, "%d", port); newip.s = ip_addr2a(&msg->rcv.dst_ip); newip.len = strlen(newip.s); cldelta = 0; if (alter_mediaip(msg, &body, &oldip, &newip, &cldelta, 0) == -1) return -1; if (oldip1.len > 0 && alter_mediaip(msg, &body1, &oldip1, &newip, &cldelta, 0) == -1) return -1; if (alter_mediaport(msg, &body, &oldport, &newport, &cldelta, 0) == -1) return -1; if (cldelta == 0) return 1; return (update_clen(msg, body.len + cldelta)); }
static int fix_nated_sdp_f(struct sip_msg* msg, char* str1, char* str2) { str body, body1, oldip, oldip1, newip; int level, added_len; char *buf; struct lump* anchor; level = (int)(long)str1; added_len = 0; if (extract_body(msg, &body) == -1 || body.len == 0) { LOG(L_ERR,"ERROR: fix_nated_sdp: cannot extract body from msg!\n"); return -1; } if (level & ADD_ADIRECTION) { anchor = anchor_lump(&(msg->add_rm), body.s + body.len - msg->buf, 0, 0); if (anchor == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: anchor_lump failed\n"); return -1; } buf = pkg_malloc(ADIRECTION_LEN * sizeof(char)); if (buf == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: out of memory\n"); return -1; } memcpy(buf, ADIRECTION, ADIRECTION_LEN); if (insert_new_lump_after(anchor, buf, ADIRECTION_LEN, 0) == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: insert_new_lump_after failed\n"); pkg_free(buf); return -1; } added_len += ADIRECTION_LEN; } if (level & FIX_MEDIAIP) { if (extract_mediaip(&body, &oldip) == -1) { LOG(L_ERR, "ERROR: fix_nated_sdp: can't extract media IP from the SDP\n"); goto finalise; } body1.s = oldip.s + oldip.len; body1.len = body.s + body.len - body1.s; if (extract_mediaip(&body1, &oldip1) == -1) { oldip1.len = 0; } newip.s = ip_addr2a(&msg->rcv.src_ip); newip.len = strlen(newip.s); if (alter_mediaip(msg, &body, &oldip, &newip, &added_len, 1) == -1) { LOG(L_ERR, "ERROR: fix_nated_sdp: can't alter media IP"); return -1; } if (oldip1.len > 0 && alter_mediaip(msg, &body, &oldip1, &newip, &added_len, 0) == -1) { LOG(L_ERR, "ERROR: fix_nated_sdp: can't alter media IP"); return -1; } } finalise: /* Check that Content-Length needs to be updated */ if (added_len != 0) { return (update_clen(msg, body.len + added_len)); } return 1; }
static int force_rtp_proxy2_f(struct sip_msg* msg, char* str1, char* str2) { str body, body1, oldport, oldip, newport, newip; str callid, from_tag, to_tag, tmp; int create, port, len, asymmetric, flookup, argc, proxied, real; int oidx, pf=0, pf1, force, node_idx; char opts[16]; char *cp, *cp1; char *cpend, *next; char **ap, *argv[10]; struct lump* anchor; struct rtpp_node *node; struct iovec v[14] = { {NULL, 0}, /* command */ {NULL, 0}, /* options */ {" ", 1}, /* separator */ {NULL, 0}, /* callid */ {" ", 1}, /* separator */ {NULL, 7}, /* newip */ {" ", 1}, /* separator */ {NULL, 1}, /* oldport */ {" ", 1}, /* separator */ {NULL, 0}, /* from_tag */ {";", 1}, /* separator */ {NULL, 0}, /* medianum */ {" ", 1}, /* separator */ {NULL, 0} /* to_tag */ }; char *v1p, *v2p, *c1p, *c2p, *m1p, *m2p, *bodylimit; char medianum_buf[20]; int medianum, media_multi; str medianum_str, tmpstr1; int c1p_altered; v[1].iov_base=opts; asymmetric = flookup = force = real = 0; oidx = 1; node_idx = -1; for (cp = str1; *cp != '\0'; cp++) { switch (*cp) { case ' ': case '\t': break; case 'a': case 'A': opts[oidx++] = 'A'; asymmetric = 1; real = 1; break; case 'i': case 'I': opts[oidx++] = 'I'; break; case 'e': case 'E': opts[oidx++] = 'E'; break; case 'l': case 'L': flookup = 1; break; case 'f': case 'F': force = 1; break; case 'r': case 'R': real = 1; break; case 'n': case 'N': cp++; for (len = 0; isdigit(cp[len]); len++) continue; if (len == 0) { LOG(L_ERR, "ERROR: force_rtp_proxy2: non-negative integer" "should follow N option\n"); return -1; } node_idx = strtoul(cp, NULL, 10); cp += len - 1; break; default: LOG(L_ERR, "ERROR: force_rtp_proxy2: unknown option `%c'\n", *cp); return -1; } } if (msg->first_line.type == SIP_REQUEST && msg->first_line.u.request.method_value == METHOD_INVITE) { create = 1; } else if (msg->first_line.type == SIP_REPLY) { create = 0; } else { return -1; } /* extract_body will also parse all the headers in the message as * a side effect => don't move get_callid/get_to_tag in front of it * -- andrei */ if (extract_body(msg, &body) == -1) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't extract body " "from the message\n"); return -1; } if (get_callid(msg, &callid) == -1 || callid.len == 0) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get Call-Id field\n"); return -1; } if (get_to_tag(msg, &to_tag) == -1) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get To tag\n"); return -1; } if (get_from_tag(msg, &from_tag) == -1 || from_tag.len == 0) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't get From tag\n"); return -1; } if (flookup != 0) { if (create == 0 || to_tag.len == 0) return -1; create = 0; tmp = from_tag; from_tag = to_tag; to_tag = tmp; } proxied = 0; for (cp = body.s; (len = body.s + body.len - cp) >= ANORTPPROXY_LEN;) { cp1 = ser_memmem(cp, ANORTPPROXY, len, ANORTPPROXY_LEN); if (cp1 == NULL) break; if (cp1[-1] == '\n' || cp1[-1] == '\r') { proxied = 1; break; } cp = cp1 + ANORTPPROXY_LEN; } if (proxied != 0 && force == 0) return -1; /* * Parsing of SDP body. * It can contain a few session descriptions (each starts with * v-line), and each session may contain a few media descriptions * (each starts with m-line). * We have to change ports in m-lines, and also change IP addresses in * c-lines which can be placed either in session header (fallback for * all medias) or media description. * Ports should be allocated for any media. IPs all should be changed * to the same value (RTP proxy IP), so we can change all c-lines * unconditionally. */ bodylimit = body.s + body.len; v1p = find_sdp_line(body.s, bodylimit, 'v'); if (v1p == NULL) { LOG(L_ERR, "ERROR: force_rtp_proxy2: no sessions in SDP\n"); return -1; } v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit); media_multi = (v2p != bodylimit); v2p = v1p; medianum = 0; for(;;) { /* Per-session iteration. */ v1p = v2p; if (v1p == NULL || v1p >= bodylimit) break; /* No sessions left */ v2p = find_next_sdp_line(v1p, bodylimit, 'v', bodylimit); /* v2p is text limit for session parsing. */ m1p = find_sdp_line(v1p, v2p, 'm'); /* Have this session media description? */ if (m1p == NULL) { LOG(L_ERR, "ERROR: force_rtp_proxy2: no m= in session\n"); return -1; } /* * Find c1p only between session begin and first media. * c1p will give common c= for all medias. */ c1p = find_sdp_line(v1p, m1p, 'c'); c1p_altered = 0; /* Have session. Iterate media descriptions in session */ m2p = m1p; for (;;) { m1p = m2p; if (m1p == NULL || m1p >= v2p) break; m2p = find_next_sdp_line(m1p, v2p, 'm', v2p); /* c2p will point to per-media "c=" */ c2p = find_sdp_line(m1p, m2p, 'c'); /* Extract address and port */ tmpstr1.s = c2p ? c2p : c1p; if (tmpstr1.s == NULL) { /* No "c=" */ LOG(L_ERR, "ERROR: force_rtp_proxy2: can't" " find media IP in the message\n"); return -1; } tmpstr1.len = v2p - tmpstr1.s; /* limit is session limit text */ if (extract_mediaip(&tmpstr1, &oldip, &pf) == -1) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't" " extract media IP from the message\n"); return -1; } tmpstr1.s = m1p; tmpstr1.len = m2p - m1p; if (extract_mediaport(&tmpstr1, &oldport) == -1) { LOG(L_ERR, "ERROR: force_rtp_proxy2: can't" " extract media port from the message\n"); return -1; } ++medianum; if (asymmetric != 0 || real != 0) { newip = oldip; } else { newip.s = ip_addr2a(&msg->rcv.src_ip); newip.len = strlen(newip.s); } /* XXX must compare address families in all addresses */ if (pf == AF_INET6) { opts[oidx] = '6'; oidx++; } snprintf(medianum_buf, sizeof medianum_buf, "%d", medianum); medianum_str.s = medianum_buf; medianum_str.len = strlen(medianum_buf); opts[0] = (create == 0) ? 'L' : 'U'; v[1].iov_len = oidx; STR2IOVEC(callid, v[3]); STR2IOVEC(newip, v[5]); STR2IOVEC(oldport, v[7]); STR2IOVEC(from_tag, v[9]); if (1 || media_multi) /* XXX netch: can't choose now*/ { STR2IOVEC(medianum_str, v[11]); } else { v[10].iov_len = v[11].iov_len = 0; } STR2IOVEC(to_tag, v[13]); do { node = select_rtpp_node(callid, 1, node_idx); if (!node) { LOG(L_ERR, "ERROR: force_rtp_proxy2: no available proxies\n"); return -1; } cp = send_rtpp_command(node, v, (to_tag.len > 0) ? 14 : 12); } while (cp == NULL); /* Parse proxy reply to <argc,argv> */ argc = 0; memset(argv, 0, sizeof(argv)); cpend=cp+strlen(cp); next=eat_token_end(cp, cpend); for (ap = argv; cp<cpend; cp=next+1, next=eat_token_end(cp, cpend)){ *next=0; if (*cp != '\0') { *ap=cp; argc++; if ((char*)++ap >= ((char*)argv+sizeof(argv))) break; } } if (argc < 1) { LOG(L_ERR, "force_rtp_proxy2: no reply from rtp proxy\n"); return -1; } port = atoi(argv[0]); if (port <= 0 || port > 65535) { LOG(L_ERR, "force_rtp_proxy2: incorrect port in reply from rtp proxy\n"); return -1; } pf1 = (argc >= 3 && argv[2][0] == '6') ? AF_INET6 : AF_INET; if (isnulladdr(&oldip, pf)) { if (pf1 == AF_INET6) { newip.s = "::"; newip.len = 2; } else { newip.s = "0.0.0.0"; newip.len = 7; } } else { newip.s = (argc < 2) ? str2 : argv[1]; newip.len = strlen(newip.s); } newport.s = int2str(port, &newport.len); /* beware static buffer */ /* Alter port. */ body1.s = m1p; body1.len = bodylimit - body1.s; if (alter_mediaport(msg, &body1, &oldport, &newport, 0) == -1) return -1; /* * Alter IP. Don't alter IP common for the session * more than once. */ if (c2p != NULL || !c1p_altered) { body1.s = c2p ? c2p : c1p; body1.len = bodylimit - body1.s; if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf1, 0) == -1) return -1; if (!c2p) c1p_altered = 1; } } /* Iterate medias in session */ } /* Iterate sessions */ if (proxied == 0) { cp = pkg_malloc(ANORTPPROXY_LEN * sizeof(char)); if (cp == NULL) { LOG(L_ERR, "ERROR: force_rtp_proxy2: out of memory\n"); return -1; } anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0); if (anchor == NULL) { LOG(L_ERR, "ERROR: force_rtp_proxy2: anchor_lump failed\n"); pkg_free(cp); return -1; } memcpy(cp, ANORTPPROXY, ANORTPPROXY_LEN); if (insert_new_lump_after(anchor, cp, ANORTPPROXY_LEN, 0) == NULL) { LOG(L_ERR, "ERROR: force_rtp_proxy2: insert_new_lump_after failed\n"); pkg_free(cp); return -1; } } return 1; }
static int fix_nated_sdp_f(struct sip_msg* msg, char* str1, char* str2) { str body, body1, oldip, newip; int level, pf; char *buf; struct lump* anchor; if (get_int_fparam(&level, msg, (fparam_t*) str1) < 0) return -1; if (extract_body(msg, &body) == -1) { LOG(L_ERR,"ERROR: fix_nated_sdp: cannot extract body from msg!\n"); return -1; } if (level & (ADD_ADIRECTION | ADD_ANORTPPROXY | ADD_ADIRECTIONP)) { msg->msg_flags |= FL_FORCE_ACTIVE; anchor = anchor_lump(msg, body.s + body.len - msg->buf, 0, 0); if (anchor == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: anchor_lump failed\n"); return -1; } if (level & ADD_ADIRECTION) { buf = pkg_malloc((ADIRECTION_LEN + CRLF_LEN) * sizeof(char)); if (buf == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: out of memory\n"); return -1; } memcpy(buf, CRLF, CRLF_LEN); memcpy(buf + CRLF_LEN, ADIRECTION, ADIRECTION_LEN); if (insert_new_lump_after(anchor, buf, ADIRECTION_LEN + CRLF_LEN, 0) == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: insert_new_lump_after failed\n"); pkg_free(buf); return -1; } } if (level & ADD_ADIRECTIONP) { buf = pkg_malloc((ADIRECTIONP_LEN + CRLF_LEN) * sizeof(char)); if (buf == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: out of memory\n"); return -1; } memcpy(buf, CRLF, CRLF_LEN); memcpy(buf + CRLF_LEN, ADIRECTIONP, ADIRECTIONP_LEN); if (insert_new_lump_after(anchor, buf, ADIRECTIONP_LEN + CRLF_LEN, 0) == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: insert_new_lump_after failed\n"); pkg_free(buf); return -1; } } if (level & ADD_ANORTPPROXY) { buf = pkg_malloc((ANORTPPROXY_LEN + CRLF_LEN) * sizeof(char)); if (buf == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: out of memory\n"); return -1; } memcpy(buf, CRLF, CRLF_LEN); memcpy(buf + CRLF_LEN, ANORTPPROXY, ANORTPPROXY_LEN); if (insert_new_lump_after(anchor, buf, ANORTPPROXY_LEN + CRLF_LEN, 0) == NULL) { LOG(L_ERR, "ERROR: fix_nated_sdp: insert_new_lump_after failed\n"); pkg_free(buf); return -1; } } } if (level & FIX_MEDIP) { /* Iterate all c= and replace ips in them. */ unsigned hasreplaced = 0; int pf1 = 0; str body2; char *bodylimit = body.s + body.len; newip.s = ip_addr2a(&msg->rcv.src_ip); newip.len = strlen(newip.s); body1 = body; for(;;) { if (extract_mediaip(&body1, &oldip, &pf) == -1) break; if (pf != AF_INET) { LOG(L_ERR, "ERROR: fix_nated_sdp: " "not an IPv4 address in SDP\n"); goto finalize; } if (!pf1) pf1 = pf; else if (pf != pf1) { LOG(L_ERR, "ERROR: fix_nated_sdp: mismatching " "address families in SDP\n"); return -1; } body2.s = oldip.s + oldip.len; body2.len = bodylimit - body2.s; if (alter_mediaip(msg, &body1, &oldip, pf, &newip, pf, 1) == -1) { LOG(L_ERR, "ERROR: fix_nated_sdp: can't alter media IP\n"); return -1; } hasreplaced = 1; body1 = body2; } if (!hasreplaced) { LOG(L_ERR, "ERROR: fix_nated_sdp: can't extract media IP from the SDP\n"); goto finalize; } } finalize: return 1; }