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