1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 2008-2016. All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * %CopyrightEnd%
19  */
20 
21 /* A protocol decoder. Simple packet length extraction as well as packet
22  * body parsing with protocol specific callback interfaces (http and ssl).
23  */
24 #ifndef __PACKET_PARSER_H__
25 #define __PACKET_PARSER_H__
26 
27 #include <erl_driver.h>
28 #include "sys.h"
29 
30 
31 /* INET_LOPT_PACKET options */
32 enum PacketParseType {
33     TCP_PB_RAW      = 0,
34     TCP_PB_1        = 1,
35     TCP_PB_2        = 2,
36     TCP_PB_4        = 3,
37     TCP_PB_ASN1     = 4,
38     TCP_PB_RM       = 5,
39     TCP_PB_CDR      = 6,
40     TCP_PB_FCGI     = 7,
41     TCP_PB_LINE_LF  = 8,
42     TCP_PB_TPKT     = 9,
43     TCP_PB_HTTP     = 10,
44     TCP_PB_HTTPH    = 11,
45     TCP_PB_SSL_TLS  = 12,
46     TCP_PB_HTTP_BIN = 13,
47     TCP_PB_HTTPH_BIN = 14
48 };
49 
50 typedef struct http_atom {
51     struct http_atom* next;   /* next in bucket */
52     unsigned long h;          /* stored hash value */
53     const char* name;
54     int   len;
55     int index;                /* index in table + bit-pos */
56     ErlDrvTermData atom;      /* erlang atom rep */
57 } http_atom_t;
58 
59 typedef struct {
60     enum {
61         URI_STAR,    /* '*' */
62         URI_STRING,  /* "string(s1)" */
63         URI_ABS_PATH,/* {abs_path, "path(s1)"} */
64         URI_SCHEME,  /* {scheme, "scheme(s1)", "string(s2)"} */
65         URI_HTTP,    /* {absoluteURI, http, "host(s1)", Port, "path(s2)"} */
66         URI_HTTPS    /* {absoluteURI, https, ... */
67     } type;
68     const char* s1_ptr;
69     int s1_len;
70     const char* s2_ptr;
71     int s2_len;
72     int port; /* 0=undefined */
73 }PacketHttpURI;
74 
75 typedef int HttpResponseMessageFn(void* arg, int major, int minor, int status,
76 				  const char* phrase, int phrase_len);
77 typedef int HttpRequestMessageFn(void* arg, const http_atom_t* meth, const char* meth_ptr,
78 				 int meth_len, const PacketHttpURI*, int major, int minor);
79 typedef int HttpEohMessageFn(void *arg);
80 typedef int HttpHeaderMessageFn(void* arg, const http_atom_t* name,
81 				const char* name_ptr, int name_len,
82 				const char* oname_ptr, int oname_len,
83 				const char* value_ptr, int value_len);
84 typedef int HttpErrorMessageFn(void* arg, const char* buf, int len);
85 typedef int SslTlsFn(void* arg, unsigned type, unsigned major, unsigned minor,
86                      const char* data, int len, const char* prefix, int plen);
87 
88 typedef struct {
89     HttpResponseMessageFn* http_response;
90     HttpRequestMessageFn* http_request;
91     HttpEohMessageFn* http_eoh;
92     HttpHeaderMessageFn* http_header;
93     HttpErrorMessageFn* http_error;
94     SslTlsFn* ssl_tls;
95 }PacketCallbacks;
96 
97 
98 /* Called once at emulator start
99  */
100 void packet_parser_init(void);
101 
102 /* Returns > 0 Total packet length.
103  *         = 0 Length unknown, need more data.
104  *         < 0 Error, invalid format.
105  */
106 int packet_get_length(enum PacketParseType htype,
107 		      const char* ptr, unsigned n,  /* Bytes read so far */
108 		      unsigned max_plen,      /* Packet max length, 0=no limit */
109 		      unsigned trunc_len,     /* Truncate (lines) if longer, 0=no limit */
110 		      char     delimiter,     /* Line delimiting character */
111 		      int*     statep);       /* Internal protocol state */
112 
113 ERTS_GLB_INLINE
114 void packet_get_body(enum PacketParseType htype,
115                      const char** bufp, /* In: Packet header, Out: Packet body */
116                      int* lenp);        /* In: Packet length, Out: Body length */
117 
118 /* Returns 1 = Packet parsed and handled by callbacks.
119 **         0 = No parsing support for this packet type
120 **        -1 = Error
121 */
122 ERTS_GLB_INLINE
123 int packet_parse(enum PacketParseType htype,
124 		 const char* buf, int len, /* Total packet */
125 		 int* statep, PacketCallbacks* pcb, void* arg);
126 
127 
128 
129 /* Internals for the inlines below: */
130 
131 #define FCGI_VERSION_1 1
132 struct fcgi_head {
133     unsigned char version;
134     unsigned char type;
135     unsigned char requestIdB1;
136     unsigned char requestIdB0;
137     unsigned char contentLengthB1;
138     unsigned char contentLengthB0;
139     unsigned char paddingLength;
140     unsigned char reserved;
141     /* char data[] */
142     /* char padding[paddingLength] */
143 };
144 int packet_parse_http(const char*, int, int*, PacketCallbacks*, void*);
145 int packet_parse_ssl(const char*, int, PacketCallbacks*, void*);
146 
147 
148 #if ERTS_GLB_INLINE_INCL_FUNC_DEF
149 ERTS_GLB_INLINE
packet_get_body(enum PacketParseType htype,const char ** bufp,int * lenp)150 void packet_get_body(enum PacketParseType htype, const char** bufp, int* lenp)
151 {
152     switch (htype) {
153     case TCP_PB_1:  *bufp += 1; *lenp -= 1; break;
154     case TCP_PB_2:  *bufp += 2; *lenp -= 2; break;
155     case TCP_PB_4:  *bufp += 4; *lenp -= 4; break;
156     case TCP_PB_FCGI:
157 	*lenp -= ((struct fcgi_head*)*bufp)->paddingLength;
158         break;
159     default:
160         ;/* Return other packets "as is" */
161     }
162 }
163 
164 ERTS_GLB_INLINE
packet_parse(enum PacketParseType htype,const char * buf,int len,int * statep,PacketCallbacks * pcb,void * arg)165 int packet_parse(enum PacketParseType htype, const char* buf, int len,
166 		 int* statep, PacketCallbacks* pcb, void* arg)
167 {
168     switch (htype) {
169     case TCP_PB_HTTP:
170     case TCP_PB_HTTPH:
171     case TCP_PB_HTTP_BIN:
172     case TCP_PB_HTTPH_BIN:
173         if (packet_parse_http(buf, len, statep, pcb, arg) < 0)
174             pcb->http_error(arg, buf, len);
175         return 1;
176     case TCP_PB_SSL_TLS:
177 	return packet_parse_ssl(buf, len, pcb, arg);
178     default:;
179     }
180     return 0;
181 }
182 #endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
183 
184 #endif /* !__PACKET_PARSER_H__ */
185 
186