Browse Source

Add support for EMM filters based on section length.

Georgi Chorbadzhiyski 11 years ago
parent
commit
1fd5008263
4 changed files with 47 additions and 6 deletions
  1. 1
    0
      ChangeLog
  2. 10
    0
      FILTERING
  3. 2
    1
      data.h
  4. 34
    5
      filter.c

+ 1
- 0
ChangeLog View File

@@ -9,6 +9,7 @@ now : current
9 9
  * Add support for Griffin CAS and for DGCrypt CAS.
10 10
  * Add support for setting multicast source address /SSM/ (--input-source).
11 11
  * Add support for EMM filters similar to DVBAPI filters (match + mask).
12
+ * Add support for EMM filters based on section length.
12 13
 
13 14
 2012-09-10 : Version 9.0
14 15
  * Add --no-output-on-error (-u) option. By using this option output can be

+ 10
- 0
FILTERING View File

@@ -94,6 +94,9 @@ Currently defined command settings are:
94 94
                    Such filter is configured like that:
95 95
                      --emm-filter "accept/name=Test_Filter,match=82 aa bb cc dd,mask=ff ff ff ff f0"
96 96
 
97
+ * length=Num1 Num2 NumX
98
+                 - Match EMM packets that have section length "X".
99
+
97 100
  * offset=X      - Sets the offset at which data bytes would be checked
98 101
                    against EMM. The default offset is 0.
99 102
 
@@ -127,6 +130,13 @@ Example filters
127 130
          --emm-filter "accept/name=Bulcrypt_EMMs,match=84 aa bb cc dd,mask=ff ff ff ff f0" \
128 131
          --emm-filter "accept/name=Bulcrypt_EMMs,match=85 aa bb cc dd,mask=ff ff ff ff f0"
129 132
 
133
+    Accept Bulcrypt EMMs that have sizes 190, 240 and 0xb4
134
+
135
+       tsdecrypt ... \
136
+         --emm \
137
+         --emm-filter reject_all \
138
+         --emm-filter "accept/name=Bulcrypt_EMMs,length=190 240 0xb4"
139
+
130 140
   Bulcrypt white list example:
131 141
     Accept all EMMs except those starting with 8a 70 b4, 8b 70 b4, 8c or 8d.
132 142
 

+ 2
- 1
data.h View File

@@ -204,12 +204,13 @@ enum filter_action {
204 204
 enum filter_type {
205 205
 	FILTER_TYPE_DATA = 0,				// Compare data at offset X
206 206
 	FILTER_TYPE_MASK = 1,				// Compare data + mask
207
+	FILTER_TYPE_LENGTH = 2,				// Compare section length /EMM[2]/)
207 208
 };
208 209
 
209 210
 struct filter {
210 211
 	enum filter_action action;
211 212
 	enum filter_type type;
212
-	uint8_t		offset;					// Offset into EMM, if offset == 255 then mask exists, ignore the offset
213
+	uint8_t		offset;					// Offset into EMM
213 214
 	uint8_t		filter_len;				// Filter length
214 215
 	uint8_t		data[MAX_FILTER_LEN];	// Data | Matched bytes
215 216
 	uint8_t		mask[MAX_FILTER_LEN];	// Mask bytes

+ 34
- 5
filter.c View File

@@ -34,7 +34,7 @@ static struct filter_actions_map action_tokens[] = {
34 34
 	{ NULL,         true,  FILTER_NO_MATCH   },
35 35
 };
36 36
 
37
-enum filter_token { T_UNKNOWN, T_NAME, T_OFFSET, T_DATA, T_MATCH, T_MASK };
37
+enum filter_token { T_UNKNOWN, T_NAME, T_OFFSET, T_DATA, T_MATCH, T_MASK, T_LENGTH };
38 38
 
39 39
 struct filter_data_map {
40 40
 	const char			*token;
@@ -48,6 +48,7 @@ static struct filter_data_map data_tokens[] = {
48 48
 	{ "data",    T_DATA    },
49 49
 	{ "match",   T_MATCH   },
50 50
 	{ "mask",    T_MASK    },
51
+	{ "length",  T_LENGTH  },
51 52
 	{ NULL,      T_UNKNOWN },
52 53
 };
53 54
 
@@ -144,9 +145,22 @@ int filter_parse(char *filter_def, struct filter *filter) {
144 145
 						filter->type = FILTER_TYPE_MASK;
145 146
 						ret = parse_hex(tokdata, filter->mask, NULL, MAX_FILTER_LEN);
146 147
 						break;
147
-					default:
148
+					case T_LENGTH: {
149
+						filter->type = FILTER_TYPE_LENGTH;
150
+						int i;
151
+						char *ptr, *saveptr3 = NULL;
152
+						for (i = 0,                ptr = strtok_r(tokdata, " ", &saveptr3);
153
+						     i < MAX_FILTER_LEN && ptr;
154
+						     i++  ,                ptr = strtok_r(NULL, " ", &saveptr3))
155
+						{
156
+							filter->data[i] = strtoul(ptr, NULL, 0);
157
+						}
158
+						filter->filter_len = i;
159
+						break;
160
+					}
161
+					case T_UNKNOWN:
148 162
 						fprintf(stderr, "WARN : Unknown filter setting: %s\n", token2);
149
-					}
163
+					} // switch (data_type)
150 164
 				}
151 165
 			}
152 166
 		}
@@ -157,7 +171,7 @@ OUT:
157 171
 }
158 172
 
159 173
 void filter_dump(struct filter *filter, char *buffer, unsigned int buf_len) {
160
-	unsigned int pos = 0;
174
+	unsigned int i, pos = 0;
161 175
 	memset(buffer, 0, buf_len);
162 176
 	pos += snprintf(buffer + pos, buf_len - pos, "Action: %s",
163 177
 		filter->action == FILTER_ACCEPT_ALL ? "ACCEPT_ALL (default)" :
@@ -177,11 +191,17 @@ void filter_dump(struct filter *filter, char *buffer, unsigned int buf_len) {
177 191
 			ts_hex_dump_buf(tmp_mask, sizeof(tmp_mask), filter->mask, filter->filter_len, 0);
178 192
 			pos += snprintf(buffer + pos, buf_len - pos, " Match: %s Mask: %s", tmp_data, tmp_mask);
179 193
 			break;
194
+		case FILTER_TYPE_LENGTH:
195
+			pos += snprintf(buffer + pos, buf_len - pos, " Length:");
196
+			for (i = 0; i < filter->filter_len; i++)
197
+				pos += snprintf(buffer + pos, buf_len - pos, " 0x%02x", filter->data[i]);
198
+			break;
180 199
 		} // switch (filter->type)
181 200
 	}
182 201
 }
183 202
 
184 203
 static enum filter_action filter_match(uint8_t *data, unsigned int data_len, struct filter *filter) {
204
+	int i;
185 205
 	if (filter->action == FILTER_ACCEPT_ALL || filter->action == FILTER_REJECT_ALL)
186 206
 		return filter->action;
187 207
 	if (filter->action == FILTER_ACCEPT || filter->action == FILTER_REJECT) {
@@ -200,7 +220,6 @@ static enum filter_action filter_match(uint8_t *data, unsigned int data_len, str
200 220
 			// Check data[0] against filter->data[0]
201 221
 			if ((data[0] & filter->mask[0]) == (filter->data[0] & filter->mask[0])) {
202 222
 				matched++;
203
-				int i;
204 223
 				for (i = 1; i < filter->filter_len; i++) {
205 224
 					// Check data[3...] against filter->data[1...]
206 225
 					if ((data[i + 2] & filter->mask[i]) == (filter->data[i] & filter->mask[i]))
@@ -211,6 +230,16 @@ static enum filter_action filter_match(uint8_t *data, unsigned int data_len, str
211 230
 				return filter->action;
212 231
 			break;
213 232
 		}
233
+		case FILTER_TYPE_LENGTH: {
234
+			if (data_len < 3)
235
+				return FILTER_NO_MATCH;
236
+			for (i = 0; i < filter->filter_len; i++) {
237
+				// data[2] holds the section length (not quite, but close to what
238
+				// we need, because length= can contain sizes > 255)
239
+				if (data[2] == filter->data[i])
240
+					return filter->action;
241
+			}
242
+		}
214 243
 		} // switch (filter->type)
215 244
 	}
216 245
 	return FILTER_NO_MATCH;

Loading…
Cancel
Save