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
  * Add support for Griffin CAS and for DGCrypt CAS.
9
  * Add support for Griffin CAS and for DGCrypt CAS.
10
  * Add support for setting multicast source address /SSM/ (--input-source).
10
  * Add support for setting multicast source address /SSM/ (--input-source).
11
  * Add support for EMM filters similar to DVBAPI filters (match + mask).
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
 2012-09-10 : Version 9.0
14
 2012-09-10 : Version 9.0
14
  * Add --no-output-on-error (-u) option. By using this option output can be
15
  * Add --no-output-on-error (-u) option. By using this option output can be

+ 10
- 0
FILTERING View File

94
                    Such filter is configured like that:
94
                    Such filter is configured like that:
95
                      --emm-filter "accept/name=Test_Filter,match=82 aa bb cc dd,mask=ff ff ff ff f0"
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
  * offset=X      - Sets the offset at which data bytes would be checked
100
  * offset=X      - Sets the offset at which data bytes would be checked
98
                    against EMM. The default offset is 0.
101
                    against EMM. The default offset is 0.
99
 
102
 
127
          --emm-filter "accept/name=Bulcrypt_EMMs,match=84 aa bb cc dd,mask=ff ff ff ff f0" \
130
          --emm-filter "accept/name=Bulcrypt_EMMs,match=84 aa bb cc dd,mask=ff ff ff ff f0" \
128
          --emm-filter "accept/name=Bulcrypt_EMMs,match=85 aa bb cc dd,mask=ff ff ff ff f0"
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
   Bulcrypt white list example:
140
   Bulcrypt white list example:
131
     Accept all EMMs except those starting with 8a 70 b4, 8b 70 b4, 8c or 8d.
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
 enum filter_type {
204
 enum filter_type {
205
 	FILTER_TYPE_DATA = 0,				// Compare data at offset X
205
 	FILTER_TYPE_DATA = 0,				// Compare data at offset X
206
 	FILTER_TYPE_MASK = 1,				// Compare data + mask
206
 	FILTER_TYPE_MASK = 1,				// Compare data + mask
207
+	FILTER_TYPE_LENGTH = 2,				// Compare section length /EMM[2]/)
207
 };
208
 };
208
 
209
 
209
 struct filter {
210
 struct filter {
210
 	enum filter_action action;
211
 	enum filter_action action;
211
 	enum filter_type type;
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
 	uint8_t		filter_len;				// Filter length
214
 	uint8_t		filter_len;				// Filter length
214
 	uint8_t		data[MAX_FILTER_LEN];	// Data | Matched bytes
215
 	uint8_t		data[MAX_FILTER_LEN];	// Data | Matched bytes
215
 	uint8_t		mask[MAX_FILTER_LEN];	// Mask bytes
216
 	uint8_t		mask[MAX_FILTER_LEN];	// Mask bytes

+ 34
- 5
filter.c View File

34
 	{ NULL,         true,  FILTER_NO_MATCH   },
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
 struct filter_data_map {
39
 struct filter_data_map {
40
 	const char			*token;
40
 	const char			*token;
48
 	{ "data",    T_DATA    },
48
 	{ "data",    T_DATA    },
49
 	{ "match",   T_MATCH   },
49
 	{ "match",   T_MATCH   },
50
 	{ "mask",    T_MASK    },
50
 	{ "mask",    T_MASK    },
51
+	{ "length",  T_LENGTH  },
51
 	{ NULL,      T_UNKNOWN },
52
 	{ NULL,      T_UNKNOWN },
52
 };
53
 };
53
 
54
 
144
 						filter->type = FILTER_TYPE_MASK;
145
 						filter->type = FILTER_TYPE_MASK;
145
 						ret = parse_hex(tokdata, filter->mask, NULL, MAX_FILTER_LEN);
146
 						ret = parse_hex(tokdata, filter->mask, NULL, MAX_FILTER_LEN);
146
 						break;
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
 						fprintf(stderr, "WARN : Unknown filter setting: %s\n", token2);
162
 						fprintf(stderr, "WARN : Unknown filter setting: %s\n", token2);
149
-					}
163
+					} // switch (data_type)
150
 				}
164
 				}
151
 			}
165
 			}
152
 		}
166
 		}
157
 }
171
 }
158
 
172
 
159
 void filter_dump(struct filter *filter, char *buffer, unsigned int buf_len) {
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
 	memset(buffer, 0, buf_len);
175
 	memset(buffer, 0, buf_len);
162
 	pos += snprintf(buffer + pos, buf_len - pos, "Action: %s",
176
 	pos += snprintf(buffer + pos, buf_len - pos, "Action: %s",
163
 		filter->action == FILTER_ACCEPT_ALL ? "ACCEPT_ALL (default)" :
177
 		filter->action == FILTER_ACCEPT_ALL ? "ACCEPT_ALL (default)" :
177
 			ts_hex_dump_buf(tmp_mask, sizeof(tmp_mask), filter->mask, filter->filter_len, 0);
191
 			ts_hex_dump_buf(tmp_mask, sizeof(tmp_mask), filter->mask, filter->filter_len, 0);
178
 			pos += snprintf(buffer + pos, buf_len - pos, " Match: %s Mask: %s", tmp_data, tmp_mask);
192
 			pos += snprintf(buffer + pos, buf_len - pos, " Match: %s Mask: %s", tmp_data, tmp_mask);
179
 			break;
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
 		} // switch (filter->type)
199
 		} // switch (filter->type)
181
 	}
200
 	}
182
 }
201
 }
183
 
202
 
184
 static enum filter_action filter_match(uint8_t *data, unsigned int data_len, struct filter *filter) {
203
 static enum filter_action filter_match(uint8_t *data, unsigned int data_len, struct filter *filter) {
204
+	int i;
185
 	if (filter->action == FILTER_ACCEPT_ALL || filter->action == FILTER_REJECT_ALL)
205
 	if (filter->action == FILTER_ACCEPT_ALL || filter->action == FILTER_REJECT_ALL)
186
 		return filter->action;
206
 		return filter->action;
187
 	if (filter->action == FILTER_ACCEPT || filter->action == FILTER_REJECT) {
207
 	if (filter->action == FILTER_ACCEPT || filter->action == FILTER_REJECT) {
200
 			// Check data[0] against filter->data[0]
220
 			// Check data[0] against filter->data[0]
201
 			if ((data[0] & filter->mask[0]) == (filter->data[0] & filter->mask[0])) {
221
 			if ((data[0] & filter->mask[0]) == (filter->data[0] & filter->mask[0])) {
202
 				matched++;
222
 				matched++;
203
-				int i;
204
 				for (i = 1; i < filter->filter_len; i++) {
223
 				for (i = 1; i < filter->filter_len; i++) {
205
 					// Check data[3...] against filter->data[1...]
224
 					// Check data[3...] against filter->data[1...]
206
 					if ((data[i + 2] & filter->mask[i]) == (filter->data[i] & filter->mask[i]))
225
 					if ((data[i + 2] & filter->mask[i]) == (filter->data[i] & filter->mask[i]))
211
 				return filter->action;
230
 				return filter->action;
212
 			break;
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
 		} // switch (filter->type)
243
 		} // switch (filter->type)
215
 	}
244
 	}
216
 	return FILTER_NO_MATCH;
245
 	return FILTER_NO_MATCH;

Loading…
Cancel
Save