changeset 49:dec31b1a8b96

sip-in: check Require and Supported
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 06 Sep 2022 22:57:16 -0800
parents 8117d8ee44a5
children daf1c26d7ae2
files libsip/Makefile libsip/req_supp.c libsip/req_supp.h sip-in/invite.c
diffstat 4 files changed, 114 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/libsip/Makefile	Tue Sep 06 22:07:51 2022 -0800
+++ b/libsip/Makefile	Tue Sep 06 22:57:16 2022 -0800
@@ -1,6 +1,7 @@
 CC=	gcc
 CFLAGS=	-O2
-OBJS=	get_header.o out_msg.o primary_parse.o uas_basic.o uri_utils.o
+OBJS=	get_header.o out_msg.o primary_parse.o req_supp.o uas_basic.o \
+	uri_utils.o
 LIB=	libsip.a
 
 all:	${LIB}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libsip/req_supp.c	Tue Sep 06 22:57:16 2022 -0800
@@ -0,0 +1,77 @@
+/*
+ * Here we parse Require and Supported headers in a SIP request,
+ * checking whether our supported extensions are also supported
+ * or required by the client, and catching any client requirements
+ * which we don't support.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include "parse.h"
+#include "req_supp.h"
+
+parse_require_supported(msg, lsupp, nlsupp, unsupp)
+	struct sip_pkt_rx *msg;
+	struct supported_ext *lsupp;
+	unsigned nlsupp;
+	char **unsupp;
+{
+	struct sip_parse_hdr *hdr, *endhdr;
+	char *cp, *np;
+	unsigned n;
+
+	endhdr = msg->hdr_fields + msg->num_hdr_fields;
+	/* check Require first */
+	for (hdr = msg->hdr_fields; hdr < endhdr; hdr++) {
+		if (strcasecmp(hdr->field_name, "Require"))
+			continue;
+		cp = hdr->field_value;
+		for (;;) {
+			while (isspace(*cp) || *cp == ',')
+				cp++;
+			if (!*cp)
+				break;
+			np = cp;
+			while (*cp && !isspace(*cp) && *cp != ',')
+				cp++;
+			if (*cp)
+				*cp++ = '\0';
+			for (n = 0; n < nlsupp; n++) {
+				if (!strcasecmp(np, lsupp[n].name)) {
+					*lsupp[n].req_flag = 1;
+					break;
+				} else {
+					if (unsupp)
+						*unsupp = np;
+					return(-1);
+				}
+			}
+		}
+	}
+	/* now check Supported */
+	for (hdr = msg->hdr_fields; hdr < endhdr; hdr++) {
+		if (strcasecmp(hdr->field_name, "Supported") &&
+		    strcasecmp(hdr->field_name, "k"))
+			continue;
+		cp = hdr->field_value;
+		for (;;) {
+			while (isspace(*cp) || *cp == ',')
+				cp++;
+			if (!*cp)
+				break;
+			np = cp;
+			while (*cp && !isspace(*cp) && *cp != ',')
+				cp++;
+			if (*cp)
+				*cp++ = '\0';
+			for (n = 0; n < nlsupp; n++) {
+				if (!strcasecmp(np, lsupp[n].name)) {
+					*lsupp[n].sup_flag = 1;
+					break;
+				}
+			}
+		}
+	}
+	return(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libsip/req_supp.h	Tue Sep 06 22:57:16 2022 -0800
@@ -0,0 +1,9 @@
+/*
+ * Data structure for parsing Require and Supported header fields
+ */
+
+struct supported_ext {
+	char	*name;
+	int	*req_flag;
+	int	*sup_flag;
+};
--- a/sip-in/invite.c	Tue Sep 06 22:07:51 2022 -0800
+++ b/sip-in/invite.c	Tue Sep 06 22:57:16 2022 -0800
@@ -13,8 +13,11 @@
 #include <unistd.h>
 #include "../libsip/parse.h"
 #include "../libsip/uas_basic.h"
+#include "../libsip/req_supp.h"
 #include "../libsip/out_msg.h"
 
+extern int cfg_use_100rel;
+
 void
 handle_sip_invite(req, ess, sin)
 	struct sip_pkt_rx *req;
@@ -23,6 +26,9 @@
 {
 	char uri_user[13], *called_nanp;
 	struct sip_msg_out resp;
+	struct supported_ext supp_ext;
+	char *unsup_ext;
+	int ext_100rel_req, ext_100rel_sup, use_100rel;
 	int rc;
 
 	/* check for existing Call-ID will go here */
@@ -33,7 +39,7 @@
 			"416 Request-URI is not a NANP number");
 error_resp:	rc = add_resp_basic_headers(&resp, ess, req->req_method);
 		if (rc < 0) {
-			syslog(LOG_ERR,
+error_resp_toolong:	syslog(LOG_ERR,
 				"INVITE error response length exceeded");
 			return;
 		}
@@ -67,9 +73,27 @@
 			"404 Called number does not belong here");
 		goto error_resp;
 	}
+	/* check 100rel and catch any unsupported requirements */
+	supp_ext.name = "100rel";
+	supp_ext.req_flag = &ext_100rel_req;
+	supp_ext.sup_flag = &ext_100rel_sup;
+	ext_100rel_req = ext_100rel_sup = 0;
+	rc = parse_require_supported(req, &supp_ext, 1, &unsup_ext);
+	if (rc < 0) {
+		start_response_out_msg(&resp, "420 Extension not supported");
+		rc = out_msg_add_header(&resp, "Unsupported", unsup_ext);
+		if (rc < 0)
+			goto error_resp_toolong;
+		goto error_resp;
+	}
+	if (ext_100rel_req)
+		use_100rel = 1;
+	else if (ext_100rel_sup)
+		use_100rel = cfg_use_100rel;
+	else
+		use_100rel = 0;
 	/*
 	 * Remaining checks to be implemented:
-	 * Require and Supported headers
 	 * SDP message body
 	 */
 }